mirror of https://github.com/CGAL/cgal
Externalize ids printing to lighten the polyhedron_item and to make it easier to give it to the SM_item
This commit is contained in:
parent
13723a704f
commit
959a985dae
|
|
@ -151,7 +151,10 @@ struct Scene_polyhedron_item_priv{
|
|||
bool plugin_has_set_color_vector_m;
|
||||
bool is_multicolor;
|
||||
void killIds();
|
||||
void fillTargetedIds(const Polyhedron::Facet_handle& selected_fh, const Kernel::Point_3 &point_under, const qglviewer::Vec &offset);
|
||||
void fillTargetedIds(const Polyhedron::Facet_handle& selected_fh,
|
||||
const Kernel::Point_3 &point_under,
|
||||
CGAL::Three::Viewer_interface *viewer,
|
||||
const qglviewer::Vec &offset);
|
||||
Scene_polyhedron_item* item;
|
||||
Polyhedron *poly;
|
||||
double volume, area;
|
||||
|
|
@ -1775,377 +1778,77 @@ CGAL::Three::Scene_item::Header_data Scene_polyhedron_item::header() const
|
|||
return data;
|
||||
}
|
||||
|
||||
template<typename Handle>
|
||||
struct KRingPMAP{
|
||||
typedef Handle key_type;
|
||||
typedef bool value_type;
|
||||
typedef value_type reference;
|
||||
typedef boost::read_write_property_map_tag category;
|
||||
std::vector<bool>* vec;
|
||||
|
||||
KRingPMAP(std::vector<bool>* vec)
|
||||
:vec(vec){}
|
||||
|
||||
friend value_type get(const KRingPMAP& map, const key_type& f){
|
||||
return (*map.vec)[f->id()];
|
||||
}
|
||||
friend void put(KRingPMAP& map, const key_type& f, const value_type i){
|
||||
(*map.vec)[f->id()] = i;
|
||||
}
|
||||
};
|
||||
|
||||
struct EdgeKRingPMAP{
|
||||
typedef boost::graph_traits<Polyhedron>::edge_descriptor key_type;
|
||||
typedef bool value_type;
|
||||
typedef value_type reference;
|
||||
typedef boost::read_write_property_map_tag category;
|
||||
std::vector<bool>* vec;
|
||||
Polyhedron* poly;
|
||||
|
||||
EdgeKRingPMAP(std::vector<bool>* vec, Polyhedron* poly)
|
||||
:vec(vec), poly(poly){}
|
||||
|
||||
friend value_type get(const EdgeKRingPMAP& map, const key_type& f){
|
||||
return (*map.vec)[halfedge(f, *map.poly)->id()/2];
|
||||
}
|
||||
friend void put(EdgeKRingPMAP& map, const key_type& f, const value_type i){
|
||||
(*map.vec)[halfedge(f, *map.poly)->id()/2] = i;
|
||||
}
|
||||
};
|
||||
|
||||
#include "id_printing.h"
|
||||
void Scene_polyhedron_item::printPrimitiveId(QPoint point, CGAL::Three::Viewer_interface *viewer)
|
||||
{
|
||||
if(d->all_primitives_displayed)
|
||||
return;
|
||||
bool found = false;
|
||||
qglviewer::Vec point_under = viewer->camera()->pointUnderPixel(point,found);
|
||||
typedef Input_facets_AABB_tree Tree;
|
||||
typedef Tree::Intersection_and_primitive_id<Kernel::Ray_3>::Type Intersection_and_primitive_id;
|
||||
|
||||
Tree* aabb_tree = static_cast<Input_facets_AABB_tree*>(d->get_aabb_tree());
|
||||
if(!aabb_tree)
|
||||
return;
|
||||
Polyhedron::Facet_handle selected_fh;
|
||||
Kernel::Point_3 pt_under;
|
||||
const qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(QGLViewer::QGLViewerPool().first())->offset();
|
||||
|
||||
//find clicked facet
|
||||
qglviewer::Vec dir = point_under - viewer->camera()->position();
|
||||
const Kernel::Point_3 ray_origin(viewer->camera()->position().x - offset.x,
|
||||
viewer->camera()->position().y - offset.y,
|
||||
viewer->camera()->position().z - offset.z);
|
||||
|
||||
const Kernel::Vector_3 ray_dir(dir.x, dir.y, dir.z);
|
||||
const Kernel::Ray_3 ray(ray_origin, ray_dir);
|
||||
typedef std::list<Intersection_and_primitive_id> Intersections;
|
||||
Intersections intersections;
|
||||
aabb_tree->all_intersections(ray, std::back_inserter(intersections));
|
||||
|
||||
if(intersections.empty())
|
||||
return;
|
||||
Intersections::iterator closest = intersections.begin();
|
||||
const Kernel::Point_3* closest_point =
|
||||
boost::get<Kernel::Point_3>(&closest->first);
|
||||
for(Intersections::iterator
|
||||
it = boost::next(intersections.begin()),
|
||||
end = intersections.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
if(! closest_point) {
|
||||
closest = it;
|
||||
}
|
||||
else {
|
||||
const Kernel::Point_3* it_point =
|
||||
boost::get<Kernel::Point_3>(&it->first);
|
||||
if(it_point &&
|
||||
(ray_dir * (*it_point - *closest_point)) < 0)
|
||||
{
|
||||
closest = it;
|
||||
closest_point = it_point;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!closest_point)
|
||||
return;
|
||||
Kernel::Point_3 pt_under(point_under.x, point_under.y, point_under.z);
|
||||
Polyhedron::Facet_handle selected_fh = closest->second;
|
||||
d->fillTargetedIds(selected_fh, pt_under, offset);
|
||||
find_primitive_id(point, aabb_tree, viewer, selected_fh, pt_under);
|
||||
d->fillTargetedIds(selected_fh, pt_under, viewer, offset);
|
||||
|
||||
}
|
||||
void Scene_polyhedron_item_priv::fillTargetedIds(const Polyhedron::Facet_handle& selected_fh,
|
||||
const Kernel::Point_3& pt_under,
|
||||
CGAL::Three::Viewer_interface *viewer,
|
||||
const qglviewer::Vec& offset)
|
||||
{
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
std::vector<Polyhedron::Vertex_handle> displayed_vertices;
|
||||
std::vector<boost::graph_traits<Polyhedron>::edge_descriptor> displayed_edges;
|
||||
std::vector<Polyhedron::Facet_handle> displayed_faces;
|
||||
//Test spots around facet to find the closest to point
|
||||
compute_displayed_ids(*poly,
|
||||
viewer,
|
||||
selected_fh,
|
||||
pt_under,
|
||||
offset,
|
||||
item->textVItems,
|
||||
item->textEItems,
|
||||
item->textFItems,
|
||||
&targeted_id,
|
||||
&all_primitives_displayed);
|
||||
|
||||
double min_dist = (std::numeric_limits<double>::max)();
|
||||
|
||||
// test the vertices of the closest face
|
||||
BOOST_FOREACH(Polyhedron::Vertex_handle vh, vertices_around_face(selected_fh->halfedge(), *poly))
|
||||
{
|
||||
Kernel::Point_3 test=Kernel::Point_3(vh->point().x()+offset.x,
|
||||
vh->point().y()+offset.y,
|
||||
vh->point().z()+offset.z);
|
||||
double dist = CGAL::squared_distance(test, pt_under);
|
||||
if( dist < min_dist){
|
||||
min_dist = dist;
|
||||
displayed_vertices.clear();
|
||||
displayed_vertices.push_back(vh);
|
||||
}
|
||||
}
|
||||
QVector3D point(displayed_vertices[0]->point().x(),
|
||||
displayed_vertices[0]->point().y(),
|
||||
displayed_vertices[0]->point().z());
|
||||
|
||||
//test if we want to erase or not
|
||||
BOOST_FOREACH(TextItem* text_item, targeted_id)
|
||||
{
|
||||
if(text_item->position() == point)
|
||||
{
|
||||
//hide and stop
|
||||
killIds();
|
||||
return;
|
||||
}
|
||||
}
|
||||
killIds();
|
||||
// test the midpoint of edges of the closest face
|
||||
BOOST_FOREACH(boost::graph_traits<Polyhedron>::halfedge_descriptor e, halfedges_around_face(selected_fh->halfedge(), *poly))
|
||||
{
|
||||
Kernel::Point_3 test=CGAL::midpoint(source(e, *poly)->point(),target(e, *poly)->point());
|
||||
test = Kernel::Point_3(test.x()+offset.x,
|
||||
test.y()+offset.y,
|
||||
test.z()+offset.z);
|
||||
double dist = CGAL::squared_distance(test, pt_under);
|
||||
if(dist < min_dist){
|
||||
min_dist = dist;
|
||||
displayed_vertices.clear();
|
||||
displayed_edges.clear();
|
||||
displayed_edges.push_back(edge(e, *poly));
|
||||
}
|
||||
}
|
||||
// test the centroid of the closest face
|
||||
double x(0), y(0), z(0);
|
||||
int total(0);
|
||||
BOOST_FOREACH(Polyhedron::Vertex_handle vh, vertices_around_face(selected_fh->halfedge(), *poly))
|
||||
{
|
||||
x+=vh->point().x();
|
||||
y+=vh->point().y();
|
||||
z+=vh->point().z();
|
||||
++total;
|
||||
}
|
||||
|
||||
Kernel::Point_3 test(x/total+offset.x,
|
||||
y/total+offset.y,
|
||||
z/total+offset.z);
|
||||
double dist = CGAL::squared_distance(test, pt_under);
|
||||
if(dist < min_dist){
|
||||
min_dist = dist;
|
||||
displayed_vertices.clear();
|
||||
displayed_edges.clear();
|
||||
displayed_faces.clear();
|
||||
displayed_faces.push_back(selected_fh);
|
||||
}
|
||||
|
||||
if(!displayed_vertices.empty())
|
||||
{
|
||||
BOOST_FOREACH(Polyhedron::Facet_handle f, CGAL::faces_around_target(displayed_vertices[0]->halfedge(), *poly))
|
||||
{
|
||||
displayed_faces.push_back(f);
|
||||
}
|
||||
BOOST_FOREACH(Polyhedron::Halfedge_handle h, CGAL::halfedges_around_target(displayed_vertices[0]->halfedge(), *poly))
|
||||
{
|
||||
displayed_edges.push_back(edge(h, *poly));
|
||||
}
|
||||
}
|
||||
else if(!displayed_edges.empty())
|
||||
{
|
||||
displayed_vertices.push_back(halfedge(displayed_edges[0], *poly)->vertex());
|
||||
displayed_vertices.push_back(halfedge(displayed_edges[0], *poly)->opposite()->vertex());
|
||||
|
||||
displayed_faces.push_back(halfedge(displayed_edges[0], *poly)->facet());
|
||||
displayed_faces.push_back(halfedge(displayed_edges[0], *poly)->opposite()->facet());
|
||||
}
|
||||
|
||||
else if(!displayed_faces.empty())
|
||||
{
|
||||
BOOST_FOREACH(Polyhedron::Halfedge_handle h, CGAL::halfedges_around_face(displayed_faces[0]->halfedge(), *poly))
|
||||
{
|
||||
displayed_edges.push_back(edge(h, *poly));
|
||||
displayed_vertices.push_back(h->vertex());
|
||||
}
|
||||
}
|
||||
//fill TextItems
|
||||
std::vector<bool> vertex_selection(false);
|
||||
vertex_selection.resize(num_vertices(*poly));
|
||||
KRingPMAP<Polyhedron::Vertex_handle> vpmap(&vertex_selection);
|
||||
BOOST_FOREACH(Polyhedron::Vertex_handle v_h, displayed_vertices)
|
||||
put(vpmap, v_h, true);
|
||||
CGAL::expand_vertex_selection(displayed_vertices,
|
||||
*poly,
|
||||
1,
|
||||
vpmap,
|
||||
std::back_inserter(displayed_vertices));
|
||||
|
||||
std::vector<bool> edge_selection(false);
|
||||
edge_selection.resize(num_edges(*poly));
|
||||
EdgeKRingPMAP epmap(&edge_selection, poly);
|
||||
BOOST_FOREACH(boost::graph_traits<Polyhedron>::edge_descriptor e_d, displayed_edges)
|
||||
put(epmap, e_d, true);
|
||||
CGAL::expand_edge_selection(displayed_edges,
|
||||
*poly,
|
||||
1,
|
||||
epmap,
|
||||
std::back_inserter(displayed_edges));
|
||||
|
||||
std::vector<bool> face_selection(false);
|
||||
face_selection.resize(num_faces(*poly));
|
||||
KRingPMAP<Polyhedron::Facet_handle> fpmap(&face_selection);
|
||||
BOOST_FOREACH(Polyhedron::Facet_handle f_h, displayed_faces)
|
||||
put(fpmap, f_h, true);
|
||||
CGAL::expand_face_selection(displayed_faces,
|
||||
*poly,
|
||||
1,
|
||||
fpmap,
|
||||
std::back_inserter(displayed_faces));
|
||||
|
||||
BOOST_FOREACH(Polyhedron::Vertex_handle vh, displayed_vertices)
|
||||
{
|
||||
Kernel::Point_3 pos=Kernel::Point_3(vh->point().x()+offset.x,
|
||||
vh->point().y()+offset.y,
|
||||
vh->point().z()+offset.z);
|
||||
TextItem* text_item = new TextItem(pos.x(), pos.y(), pos.z(), QString("%1").arg(vh->id()), true, font, Qt::red);
|
||||
item->textVItems->append(text_item);
|
||||
targeted_id.push_back(text_item);
|
||||
}
|
||||
if(vertices_displayed)
|
||||
item->showVertices(true);
|
||||
BOOST_FOREACH(boost::graph_traits<Polyhedron>::edge_descriptor e, displayed_edges)
|
||||
{
|
||||
Polyhedron::Halfedge_handle h(halfedge(e, *poly));
|
||||
Kernel::Point_3 pos=CGAL::midpoint(source(h, *poly)->point(),target(h, *poly)->point());
|
||||
pos = Kernel::Point_3(pos.x()+offset.x,
|
||||
pos.y()+offset.y,
|
||||
pos.z()+offset.z);
|
||||
|
||||
TextItem* text_item = new TextItem(pos.x(), pos.y(), pos.z(), QString("%1").arg(h->id()/2), true, font, Qt::green);
|
||||
item->textEItems->append(text_item);
|
||||
}
|
||||
if(edges_displayed)
|
||||
item->showEdges(true);
|
||||
|
||||
BOOST_FOREACH(Polyhedron::Facet_handle f, displayed_faces)
|
||||
{
|
||||
double x(0), y(0), z(0);
|
||||
int total(0);
|
||||
BOOST_FOREACH(Polyhedron::Vertex_handle vh, vertices_around_face(f->halfedge(), *poly))
|
||||
{
|
||||
x+=vh->point().x();
|
||||
y+=vh->point().y();
|
||||
z+=vh->point().z();
|
||||
++total;
|
||||
}
|
||||
|
||||
Kernel::Point_3 pos(x/total+offset.x,
|
||||
y/total+offset.y,
|
||||
z/total+offset.z);
|
||||
TextItem* text_item = new TextItem(pos.x(), pos.y(), pos.z(), QString("%1").arg(f->id()), true, font, Qt::blue);
|
||||
item->textFItems->append(text_item);
|
||||
}
|
||||
if(faces_displayed)
|
||||
item->showFaces(true);
|
||||
|
||||
}
|
||||
|
||||
bool Scene_polyhedron_item::printVertexIds(CGAL::Three::Viewer_interface *viewer) const
|
||||
{
|
||||
TextRenderer *renderer = viewer->textRenderer();
|
||||
if(d->vertices_displayed)
|
||||
{
|
||||
const qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(QGLViewer::QGLViewerPool().first())->offset();
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
|
||||
//fills textItems
|
||||
BOOST_FOREACH(Polyhedron::Vertex_const_handle vh, vertices(*d->poly))
|
||||
{
|
||||
const Point& p = Point(vh->point().x(), vh->point().y(), vh->point().z());
|
||||
textVItems->append(new TextItem((float)p.x() + offset.x,
|
||||
(float)p.y() + offset.y,
|
||||
(float)p.z() + offset.z,
|
||||
QString("%1").arg(vh->id()), true, font, Qt::red));
|
||||
|
||||
}
|
||||
//add the QList to the render's pool
|
||||
renderer->addTextList(textVItems);
|
||||
if(textVItems->size() > static_cast<std::size_t>(renderer->getMax_textItems()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ::printVertexIds(*d->poly,
|
||||
textVItems,
|
||||
viewer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Scene_polyhedron_item::printEdgeIds(CGAL::Three::Viewer_interface *viewer) const
|
||||
{
|
||||
TextRenderer *renderer = viewer->textRenderer();
|
||||
if(d->edges_displayed)
|
||||
{
|
||||
const qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(QGLViewer::QGLViewerPool().first())->offset();
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
|
||||
BOOST_FOREACH(boost::graph_traits<Polyhedron>::edge_descriptor e, edges(*d->poly))
|
||||
{
|
||||
const Point& p1 = source(e, *d->poly)->point();
|
||||
const Point& p2 = target(e, *d->poly)->point();
|
||||
textEItems->append(new TextItem((float)(p1.x() + p2.x()) / 2 + offset.x,
|
||||
(float)(p1.y() + p2.y()) / 2 + offset.y,
|
||||
(float)(p1.z() + p2.z()) / 2 + offset.z,
|
||||
QString("%1").arg(e.halfedge()->id() / 2), true, font, Qt::green));
|
||||
}
|
||||
//add the QList to the render's pool
|
||||
renderer->addTextList(textEItems);
|
||||
if(textEItems->size() > static_cast<std::size_t>(renderer->getMax_textItems()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ::printEdgeIds(*d->poly,
|
||||
textEItems,
|
||||
viewer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Scene_polyhedron_item::printFaceIds(CGAL::Three::Viewer_interface *viewer) const
|
||||
{
|
||||
TextRenderer *renderer = viewer->textRenderer();
|
||||
if(d->faces_displayed)
|
||||
{
|
||||
const qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(QGLViewer::QGLViewerPool().first())->offset();
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
BOOST_FOREACH(Polyhedron::Facet_handle fh, faces(*d->poly))
|
||||
{
|
||||
double x(0), y(0), z(0);
|
||||
int total(0);
|
||||
BOOST_FOREACH(Polyhedron::Vertex_handle vh, vertices_around_face(fh->halfedge(), *d->poly))
|
||||
{
|
||||
x += vh->point().x();
|
||||
y += vh->point().y();
|
||||
z += vh->point().z();
|
||||
++total;
|
||||
}
|
||||
|
||||
textFItems->append(new TextItem((float)x / total + offset.x,
|
||||
(float)y / total + offset.y,
|
||||
(float)z / total + offset.z,
|
||||
QString("%1").arg(fh->id()), true, font, Qt::blue));
|
||||
}
|
||||
//add the QList to the render's pool
|
||||
renderer->addTextList(textFItems);
|
||||
if(textFItems->size() > static_cast<std::size_t>(renderer->getMax_textItems()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ::printFaceIds(*d->poly,
|
||||
textFItems,
|
||||
viewer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2154,22 +1857,12 @@ void Scene_polyhedron_item_priv::killIds()
|
|||
{
|
||||
CGAL::Three::Viewer_interface* viewer =
|
||||
qobject_cast<CGAL::Three::Viewer_interface*>(QGLViewer::QGLViewerPool().first());
|
||||
TextRenderer *renderer = viewer->textRenderer();
|
||||
BOOST_FOREACH(TextItem* it, item->textVItems->textList())
|
||||
delete it;
|
||||
BOOST_FOREACH(TextItem* it, item->textEItems->textList())
|
||||
delete it;
|
||||
BOOST_FOREACH(TextItem* it, item->textFItems->textList())
|
||||
delete it;
|
||||
item->textVItems->clear();
|
||||
renderer->removeTextList(item->textVItems);
|
||||
item->textEItems->clear();
|
||||
renderer->removeTextList(item->textEItems);
|
||||
item->textFItems->clear();
|
||||
renderer->removeTextList(item->textFItems);
|
||||
targeted_id.clear();
|
||||
all_primitives_displayed = false;
|
||||
viewer->update();
|
||||
deleteIds(viewer,
|
||||
item->textVItems,
|
||||
item->textEItems,
|
||||
item->textFItems,
|
||||
&targeted_id,
|
||||
&all_primitives_displayed);
|
||||
}
|
||||
|
||||
void Scene_polyhedron_item::printAllIds(CGAL::Three::Viewer_interface *viewer)
|
||||
|
|
@ -2182,7 +1875,6 @@ void Scene_polyhedron_item::printAllIds(CGAL::Three::Viewer_interface *viewer)
|
|||
bool s1(printVertexIds(viewer)),
|
||||
s2(printEdgeIds(viewer)),
|
||||
s3(printFaceIds(viewer));
|
||||
|
||||
if((s1 && s2 && s3))
|
||||
{
|
||||
d->all_primitives_displayed = true;
|
||||
|
|
@ -2472,152 +2164,40 @@ void Scene_polyhedron_item::zoomToId()
|
|||
QString text = QInputDialog::getText(QApplication::activeWindow(), tr("Zoom to Index"),
|
||||
tr("Simplex"), QLineEdit::Normal,
|
||||
tr("v0"), &ok);
|
||||
if (ok)
|
||||
CGAL::Three::Viewer_interface* viewer =
|
||||
qobject_cast<CGAL::Three::Viewer_interface*>(QGLViewer::QGLViewerPool().first());
|
||||
Point p;
|
||||
QString id = text.right(text.length()-1);
|
||||
int return_value = ::zoomToId(*d->poly, text, viewer, selected_fh, p);
|
||||
switch(return_value)
|
||||
{
|
||||
bool is_int;
|
||||
unsigned int id = text.right(text.length()-1).toUInt(&is_int);
|
||||
QString first = text.left(1);
|
||||
if((first != tr("v") &&
|
||||
first != tr("e") &&
|
||||
first != tr("f")) ||
|
||||
!is_int)
|
||||
{
|
||||
|
||||
QMessageBox::warning(QApplication::activeWindow(),
|
||||
"ERROR",
|
||||
tr("Input must be of the form [v/e/f][int]")
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
CGAL::Three::Viewer_interface* viewer =
|
||||
qobject_cast<CGAL::Three::Viewer_interface*>(QGLViewer::QGLViewerPool().first());
|
||||
const qglviewer::Vec offset =
|
||||
static_cast<CGAL::Three::Viewer_interface*>(QGLViewer::QGLViewerPool().first())->offset();
|
||||
|
||||
Point p;
|
||||
Kernel::Vector_3 normal;
|
||||
if(first == tr("v"))
|
||||
{
|
||||
bool found = false;
|
||||
BOOST_FOREACH(Polyhedron::Vertex_handle vh, vertices(*d->poly))
|
||||
{
|
||||
if(vh->id() == id)
|
||||
{
|
||||
p = Point(vh->point().x() + offset.x,
|
||||
vh->point().y() + offset.y,
|
||||
vh->point().z() + offset.z);
|
||||
selected_fh = vh->halfedge()->facet();
|
||||
normal = CGAL::Polygon_mesh_processing::compute_vertex_normal(vh, *d->poly);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
QMessageBox::warning(QApplication::activeWindow(),
|
||||
"ERROR",
|
||||
tr("No vertex with id %1").arg(id)
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(first == tr("e"))
|
||||
{
|
||||
bool found = false;
|
||||
BOOST_FOREACH(boost::graph_traits<Polyhedron>::edge_descriptor e, edges(*d->poly))
|
||||
{
|
||||
if(halfedge(e, *d->poly)->id()/2 == id)
|
||||
{
|
||||
const Point& p1 = source(e, *d->poly)->point();
|
||||
const Point& p2 = target(e, *d->poly)->point();
|
||||
p = Point((float)(p1.x() + p2.x()) / 2 + offset.x,
|
||||
(float)(p1.y() + p2.y()) / 2 + offset.y,
|
||||
(float)(p1.z() + p2.z()) / 2 + offset.z );
|
||||
Kernel::Vector_3 normal1 = CGAL::Polygon_mesh_processing::compute_face_normal(halfedge(e, *d->poly)->face(),
|
||||
*d->poly);
|
||||
Kernel::Vector_3 normal2 = CGAL::Polygon_mesh_processing::compute_face_normal(halfedge(e, *d->poly)->opposite()->face(),
|
||||
*d->poly);
|
||||
normal = 0.5*normal1+0.5*normal2;
|
||||
selected_fh = halfedge(e, *d->poly)->facet();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
QMessageBox::warning(QApplication::activeWindow(),
|
||||
"ERROR",
|
||||
tr("No edge with id %1").arg(id)
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else if(first == tr("f"))
|
||||
{
|
||||
bool found = false;
|
||||
double x(0), y(0), z(0);
|
||||
int total(0);
|
||||
BOOST_FOREACH(Polyhedron::Facet_handle fh, faces(*d->poly))
|
||||
{
|
||||
if(fh->id() != id)
|
||||
continue;
|
||||
BOOST_FOREACH(Polyhedron::Vertex_handle vh, vertices_around_face(fh->halfedge(), *d->poly))
|
||||
{
|
||||
x+=vh->point().x();
|
||||
y+=vh->point().y();
|
||||
z+=vh->point().z();
|
||||
++total;
|
||||
}
|
||||
p = Kernel::Point_3(x/total + offset.x,
|
||||
y/total + offset.y,
|
||||
z/total + offset.z);
|
||||
normal = CGAL::Polygon_mesh_processing::compute_face_normal(
|
||||
fh,
|
||||
*d->poly);
|
||||
selected_fh = fh;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
QMessageBox::warning(QApplication::activeWindow(),
|
||||
"ERROR",
|
||||
tr("No face with id %1").arg(id)
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
qglviewer::Quaternion new_orientation(qglviewer::Vec(0,0,-1),
|
||||
qglviewer::Vec(-normal.x(), -normal.y(), -normal.z()));
|
||||
Kernel::Point_3 new_pos = p +
|
||||
qglviewer::Vec(
|
||||
viewer->camera()->position().x - viewer->camera()->sceneCenter().x,
|
||||
viewer->camera()->position().y - viewer->camera()->sceneCenter().y,
|
||||
viewer->camera()->position().z - viewer->camera()->sceneCenter().z)
|
||||
.norm() * normal ;
|
||||
|
||||
#if QGLVIEWER_VERSION >= 0x020502
|
||||
viewer->camera()->setPivotPoint(qglviewer::Vec(p.x(),
|
||||
p.y(),
|
||||
p.z()));
|
||||
#else
|
||||
viewer->camera()->setRevolveAroundPoint(qglviewer::Vec(p.x(),
|
||||
p.y(),
|
||||
p.z()));
|
||||
#endif
|
||||
|
||||
viewer->moveCameraToCoordinates(QString("%1 %2 %3 %4 %5 %6 %7").arg(new_pos.x())
|
||||
.arg(new_pos.y())
|
||||
.arg(new_pos.z())
|
||||
.arg(new_orientation[0])
|
||||
.arg(new_orientation[1])
|
||||
.arg(new_orientation[2])
|
||||
.arg(new_orientation[3]));
|
||||
viewer->update();
|
||||
d->fillTargetedIds(selected_fh, p, offset);
|
||||
}
|
||||
case 1:
|
||||
QMessageBox::warning(QApplication::activeWindow(),
|
||||
"ERROR",
|
||||
tr("Input must be of the form [v/e/f][int]")
|
||||
);
|
||||
return;
|
||||
case 2:
|
||||
QMessageBox::warning(QApplication::activeWindow(),
|
||||
"ERROR",
|
||||
tr("No vertex with id %1").arg(id)
|
||||
);
|
||||
return;
|
||||
case 3:
|
||||
QMessageBox::warning(QApplication::activeWindow(),
|
||||
"ERROR",
|
||||
tr("No edge with id %1").arg(id)
|
||||
);
|
||||
return;
|
||||
case 4:
|
||||
QMessageBox::warning(QApplication::activeWindow(),
|
||||
"ERROR",
|
||||
tr("No face with id %1").arg(id)
|
||||
);
|
||||
return;
|
||||
default: //case 0
|
||||
d->fillTargetedIds(selected_fh, p, viewer, viewer->offset());
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool Scene_polyhedron_item::shouldDisplayIds(CGAL::Three::Scene_item *current_item) const
|
||||
|
|
|
|||
|
|
@ -0,0 +1,615 @@
|
|||
#ifndef ID_PRINTING_H
|
||||
#define ID_PRINTING_H
|
||||
#include <CGAL/Three/Viewer_interface.h>
|
||||
#include <CGAL/Three/TextRenderer.h>
|
||||
#include <CGAL/Kernel_traits.h>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||
#include <vector>
|
||||
|
||||
template<class Mesh>
|
||||
struct VKRingPMAP{
|
||||
typedef typename boost::graph_traits<Mesh>::vertex_descriptor key_type;
|
||||
typedef bool value_type;
|
||||
typedef value_type reference;
|
||||
typedef boost::read_write_property_map_tag category;
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_index_t>::type IDmap;
|
||||
std::vector<bool>* vec;
|
||||
Mesh* poly;
|
||||
IDmap idmap;
|
||||
|
||||
|
||||
VKRingPMAP(std::vector<bool>* vec, Mesh* poly)
|
||||
:vec(vec), poly(poly)
|
||||
{
|
||||
idmap = get(boost::vertex_index, *poly);
|
||||
}
|
||||
|
||||
friend value_type get(const VKRingPMAP<Mesh>& map, const key_type& f){
|
||||
return (*map.vec)[get(map.idmap, f)];
|
||||
}
|
||||
friend void put(VKRingPMAP<Mesh>& map, const key_type& f, const value_type i){
|
||||
(*map.vec)[get(map.idmap, f)] = i;
|
||||
}
|
||||
};
|
||||
template<class Mesh>
|
||||
struct EdgeKRingPMAP{
|
||||
typedef typename boost::graph_traits<Mesh>::edge_descriptor key_type;
|
||||
typedef bool value_type;
|
||||
typedef value_type reference;
|
||||
typedef boost::read_write_property_map_tag category;
|
||||
typedef typename boost::property_map<Mesh, boost::halfedge_index_t>::type IDmap;
|
||||
std::vector<bool>* vec;
|
||||
Mesh* poly;
|
||||
IDmap idmap;
|
||||
|
||||
EdgeKRingPMAP(std::vector<bool>* vec, Mesh* poly)
|
||||
:vec(vec), poly(poly)
|
||||
{
|
||||
idmap = get(boost::halfedge_index, *poly);
|
||||
}
|
||||
|
||||
friend value_type get(const EdgeKRingPMAP<Mesh>& map, const key_type& f){
|
||||
return (*map.vec)[get(map.idmap, halfedge(f, *map.poly))/2];
|
||||
}
|
||||
friend void put(EdgeKRingPMAP<Mesh>& map, const key_type& f, const value_type i){
|
||||
(*map.vec)[get(map.idmap, halfedge(f, *map.poly))/2] = i;
|
||||
}
|
||||
};
|
||||
template<class Mesh>
|
||||
struct FKRingPMAP{
|
||||
typedef typename boost::graph_traits<Mesh>::face_descriptor key_type;
|
||||
typedef bool value_type;
|
||||
typedef value_type reference;
|
||||
typedef boost::read_write_property_map_tag category;
|
||||
typedef typename boost::property_map<Mesh, boost::face_index_t>::type IDmap;
|
||||
std::vector<bool>* vec;
|
||||
Mesh* poly;
|
||||
IDmap idmap;
|
||||
|
||||
FKRingPMAP(std::vector<bool>* vec, Mesh* poly)
|
||||
:vec(vec), poly(poly)
|
||||
{
|
||||
idmap = get(boost::face_index, *poly);
|
||||
}
|
||||
|
||||
friend value_type get(const FKRingPMAP<Mesh>& map, const key_type& f){
|
||||
return (*map.vec)[get(map.idmap, f)];
|
||||
}
|
||||
friend void put(FKRingPMAP<Mesh>& map, const key_type& f, const value_type i){
|
||||
(*map.vec)[get(map.idmap, f)] = i;
|
||||
}
|
||||
};
|
||||
void deleteIds(CGAL::Three::Viewer_interface* viewer,
|
||||
TextListItem* vitems,
|
||||
TextListItem* eitems,
|
||||
TextListItem* fitems,
|
||||
std::vector<TextItem*>* targeted_ids,
|
||||
bool *all_primitives_displayed)
|
||||
{
|
||||
TextRenderer *renderer = viewer->textRenderer();
|
||||
BOOST_FOREACH(TextItem* it, vitems->textList())
|
||||
delete it;
|
||||
BOOST_FOREACH(TextItem* it, eitems->textList())
|
||||
delete it;
|
||||
BOOST_FOREACH(TextItem* it, fitems->textList())
|
||||
delete it;
|
||||
vitems->clear();
|
||||
renderer->removeTextList(vitems);
|
||||
eitems->clear();
|
||||
renderer->removeTextList(eitems);
|
||||
fitems->clear();
|
||||
renderer->removeTextList(fitems);
|
||||
targeted_ids->clear();
|
||||
*all_primitives_displayed = false;
|
||||
viewer->update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Handle, typename Point, typename Tree>
|
||||
void find_primitive_id(const QPoint& point,
|
||||
Tree* aabb_tree,
|
||||
CGAL::Three::Viewer_interface *viewer,
|
||||
Handle& selected_fh,
|
||||
Point& pt_under)
|
||||
{
|
||||
typedef typename CGAL::Kernel_traits<Point>::Kernel Traits;
|
||||
bool found = false;
|
||||
qglviewer::Vec point_under = viewer->camera()->pointUnderPixel(point,found);
|
||||
const qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(QGLViewer::QGLViewerPool().first())->offset();
|
||||
|
||||
//find clicked facet
|
||||
qglviewer::Vec dir = point_under - viewer->camera()->position();
|
||||
const Point ray_origin(viewer->camera()->position().x - offset.x,
|
||||
viewer->camera()->position().y - offset.y,
|
||||
viewer->camera()->position().z - offset.z);
|
||||
|
||||
const typename Traits::Vector_3 ray_dir(dir.x, dir.y, dir.z);
|
||||
const typename Traits::Ray_3 ray(ray_origin, ray_dir);
|
||||
|
||||
typedef typename Tree::template Intersection_and_primitive_id<typename Traits::Ray_3>::Type Intersection_and_primitive_id;
|
||||
typedef std::list<Intersection_and_primitive_id> Intersections;
|
||||
Intersections intersections;
|
||||
aabb_tree->all_intersections(ray, std::back_inserter(intersections));
|
||||
|
||||
if(intersections.empty())
|
||||
return;
|
||||
typename Intersections::iterator closest = intersections.begin();
|
||||
const Point* closest_point =
|
||||
boost::get<Point>(&closest->first);
|
||||
for(typename Intersections::iterator
|
||||
it = boost::next(intersections.begin()),
|
||||
end = intersections.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
if(! closest_point) {
|
||||
closest = it;
|
||||
}
|
||||
else {
|
||||
const Point* it_point =
|
||||
boost::get<Point>(&it->first);
|
||||
if(it_point &&
|
||||
(ray_dir * (*it_point - *closest_point)) < 0)
|
||||
{
|
||||
closest = it;
|
||||
closest_point = it_point;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!closest_point)
|
||||
return;
|
||||
pt_under = Point(point_under.x, point_under.y, point_under.z);
|
||||
selected_fh = closest->second;
|
||||
}
|
||||
|
||||
template<typename Mesh, typename Point >
|
||||
void compute_displayed_ids(Mesh& mesh,
|
||||
CGAL::Three::Viewer_interface *viewer,
|
||||
const typename boost::graph_traits<Mesh>::face_descriptor& selected_fh,
|
||||
const Point& pt_under,
|
||||
const qglviewer::Vec& offset,
|
||||
TextListItem* vitems,
|
||||
TextListItem* eitems,
|
||||
TextListItem* fitems,
|
||||
std::vector<TextItem*>* targeted_ids,
|
||||
bool *all_primitives_displayed)
|
||||
{
|
||||
typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<Mesh>::edge_descriptor edge_descriptor;
|
||||
typedef typename boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::type Ppmap;
|
||||
Ppmap ppmap = get(boost::vertex_point, mesh);
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
std::vector<vertex_descriptor> displayed_vertices;
|
||||
std::vector<edge_descriptor> displayed_edges;
|
||||
std::vector<face_descriptor> displayed_faces;
|
||||
//Test spots around facet to find the closest to point
|
||||
|
||||
double min_dist = (std::numeric_limits<double>::max)();
|
||||
|
||||
// test the vertices of the closest face
|
||||
BOOST_FOREACH(vertex_descriptor vh, vertices_around_face(halfedge(selected_fh, mesh), mesh))
|
||||
{
|
||||
Point test=Point(get(ppmap, vh).x()+offset.x,
|
||||
get(ppmap, vh).y()+offset.y,
|
||||
get(ppmap, vh).z()+offset.z);
|
||||
double dist = CGAL::squared_distance(test, pt_under);
|
||||
if( dist < min_dist){
|
||||
min_dist = dist;
|
||||
displayed_vertices.clear();
|
||||
displayed_vertices.push_back(vh);
|
||||
}
|
||||
}
|
||||
QVector3D point(get(ppmap, displayed_vertices[0]).x(),
|
||||
get(ppmap, displayed_vertices[0]).y(),
|
||||
get(ppmap, displayed_vertices[0]).z());
|
||||
|
||||
//test if we want to erase or not
|
||||
BOOST_FOREACH(TextItem* text_item, *targeted_ids)
|
||||
{
|
||||
if(text_item->position() == point)
|
||||
{
|
||||
//hide and stop
|
||||
deleteIds(viewer, vitems, eitems, fitems, targeted_ids, all_primitives_displayed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
deleteIds(viewer, vitems, eitems, fitems, targeted_ids, all_primitives_displayed);
|
||||
// test the midpoint of edges of the closest face
|
||||
BOOST_FOREACH(halfedge_descriptor e, halfedges_around_face(selected_fh->halfedge(), mesh))
|
||||
{
|
||||
Point test=CGAL::midpoint(source(e, mesh)->point(),target(e, mesh)->point());
|
||||
test = Point(test.x()+offset.x,
|
||||
test.y()+offset.y,
|
||||
test.z()+offset.z);
|
||||
double dist = CGAL::squared_distance(test, pt_under);
|
||||
if(dist < min_dist){
|
||||
min_dist = dist;
|
||||
displayed_vertices.clear();
|
||||
displayed_edges.clear();
|
||||
displayed_edges.push_back(edge(e, mesh));
|
||||
}
|
||||
}
|
||||
// test the centroid of the closest face
|
||||
double x(0), y(0), z(0);
|
||||
int total(0);
|
||||
BOOST_FOREACH(vertex_descriptor vh, vertices_around_face(selected_fh->halfedge(), mesh))
|
||||
{
|
||||
x+=get(ppmap, vh).x();
|
||||
y+=get(ppmap, vh).y();
|
||||
z+=get(ppmap, vh).z();
|
||||
++total;
|
||||
}
|
||||
|
||||
Point test(x/total+offset.x,
|
||||
y/total+offset.y,
|
||||
z/total+offset.z);
|
||||
double dist = CGAL::squared_distance(test, pt_under);
|
||||
if(dist < min_dist){
|
||||
min_dist = dist;
|
||||
displayed_vertices.clear();
|
||||
displayed_edges.clear();
|
||||
displayed_faces.clear();
|
||||
displayed_faces.push_back(selected_fh);
|
||||
}
|
||||
|
||||
if(!displayed_vertices.empty())
|
||||
{
|
||||
BOOST_FOREACH(face_descriptor f, CGAL::faces_around_target(halfedge(displayed_vertices[0],mesh), mesh))
|
||||
{
|
||||
displayed_faces.push_back(f);
|
||||
}
|
||||
BOOST_FOREACH(halfedge_descriptor h, CGAL::halfedges_around_target(halfedge(displayed_vertices[0], mesh), mesh))
|
||||
{
|
||||
displayed_edges.push_back(edge(h, mesh));
|
||||
}
|
||||
}
|
||||
else if(!displayed_edges.empty())
|
||||
{
|
||||
displayed_vertices.push_back(target(halfedge(displayed_edges[0], mesh), mesh));
|
||||
displayed_vertices.push_back(target(halfedge(displayed_edges[0], mesh)->opposite(),mesh));
|
||||
|
||||
displayed_faces.push_back(face(halfedge(displayed_edges[0], mesh),mesh));
|
||||
displayed_faces.push_back(face(halfedge(displayed_edges[0], mesh)->opposite(),mesh));
|
||||
}
|
||||
|
||||
else if(!displayed_faces.empty())
|
||||
{
|
||||
BOOST_FOREACH(halfedge_descriptor h, CGAL::halfedges_around_face(halfedge(displayed_faces[0], mesh), mesh))
|
||||
{
|
||||
displayed_edges.push_back(edge(h, mesh));
|
||||
displayed_vertices.push_back(target(h, mesh));
|
||||
}
|
||||
}
|
||||
//fill TextItems
|
||||
std::vector<bool> vertex_selection(false);
|
||||
vertex_selection.resize(num_vertices(mesh));
|
||||
VKRingPMAP<Mesh> vpmap(&vertex_selection, &mesh);
|
||||
BOOST_FOREACH(vertex_descriptor v_h, displayed_vertices)
|
||||
put(vpmap, v_h, true);
|
||||
CGAL::expand_vertex_selection(displayed_vertices,
|
||||
mesh,
|
||||
1,
|
||||
vpmap,
|
||||
std::back_inserter(displayed_vertices));
|
||||
|
||||
std::vector<bool> edge_selection(false);
|
||||
edge_selection.resize(num_edges(mesh));
|
||||
EdgeKRingPMAP<Mesh> epmap(&edge_selection, &mesh);
|
||||
BOOST_FOREACH(edge_descriptor e_d, displayed_edges)
|
||||
put(epmap, e_d, true);
|
||||
CGAL::expand_edge_selection(displayed_edges,
|
||||
mesh,
|
||||
1,
|
||||
epmap,
|
||||
std::back_inserter(displayed_edges));
|
||||
|
||||
std::vector<bool> face_selection(false);
|
||||
face_selection.resize(num_faces(mesh));
|
||||
FKRingPMAP<Mesh> fpmap(&face_selection, &mesh);
|
||||
BOOST_FOREACH(face_descriptor f_h, displayed_faces)
|
||||
put(fpmap, f_h, true);
|
||||
CGAL::expand_face_selection(displayed_faces,
|
||||
mesh,
|
||||
1,
|
||||
fpmap,
|
||||
std::back_inserter(displayed_faces));
|
||||
|
||||
BOOST_FOREACH(vertex_descriptor vh, displayed_vertices)
|
||||
{
|
||||
Point pos=Point(get(ppmap, vh).x()+offset.x,
|
||||
get(ppmap, vh).y()+offset.y,
|
||||
get(ppmap, vh).z()+offset.z);
|
||||
TextItem* text_item = new TextItem(pos.x(), pos.y(), pos.z(), QString("%1").arg(vh->id()), true, font, Qt::red);
|
||||
vitems->append(text_item);
|
||||
targeted_ids->push_back(text_item);
|
||||
}
|
||||
BOOST_FOREACH(edge_descriptor e, displayed_edges)
|
||||
{
|
||||
halfedge_descriptor h(halfedge(e, mesh));
|
||||
Point pos=CGAL::midpoint(source(h, mesh)->point(),target(h, mesh)->point());
|
||||
pos = Point(pos.x()+offset.x,
|
||||
pos.y()+offset.y,
|
||||
pos.z()+offset.z);
|
||||
|
||||
TextItem* text_item = new TextItem(pos.x(), pos.y(), pos.z(), QString("%1").arg(h->id()/2), true, font, Qt::green);
|
||||
eitems->append(text_item);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(face_descriptor f, displayed_faces)
|
||||
{
|
||||
double x(0), y(0), z(0);
|
||||
int total(0);
|
||||
BOOST_FOREACH(vertex_descriptor vh, vertices_around_face(halfedge(f, mesh), mesh))
|
||||
{
|
||||
x+=get(ppmap, vh).x();
|
||||
y+=get(ppmap, vh).y();
|
||||
z+=get(ppmap, vh).z();
|
||||
++total;
|
||||
}
|
||||
|
||||
Point pos(x/total+offset.x,
|
||||
y/total+offset.y,
|
||||
z/total+offset.z);
|
||||
TextItem* text_item = new TextItem(pos.x(), pos.y(), pos.z(), QString("%1").arg(f->id()), true, font, Qt::blue);
|
||||
fitems->append(text_item);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Mesh>
|
||||
bool printVertexIds(const Mesh& mesh,
|
||||
TextListItem* vitems,
|
||||
CGAL::Three::Viewer_interface *viewer)
|
||||
{
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::const_type Ppmap;
|
||||
typedef typename boost::property_traits<Ppmap>::value_type Point;
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_index_t>::type IDmap;
|
||||
|
||||
Ppmap ppmap = get(boost::vertex_point, mesh);
|
||||
IDmap idmap = get(boost::vertex_index, mesh);
|
||||
TextRenderer *renderer = viewer->textRenderer();
|
||||
const qglviewer::Vec offset = viewer->offset();
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
|
||||
//fills textItems
|
||||
BOOST_FOREACH(typename boost::graph_traits<Mesh>::vertex_descriptor vh, vertices(mesh))
|
||||
{
|
||||
const Point& p = get(ppmap, vh);
|
||||
vitems->append(new TextItem((float)p.x() + offset.x,
|
||||
(float)p.y() + offset.y,
|
||||
(float)p.z() + offset.z,
|
||||
QString("%1").arg(get(idmap, vh)), true, font, Qt::red));
|
||||
|
||||
}
|
||||
//add the QList to the render's pool
|
||||
renderer->addTextList(vitems);
|
||||
if(vitems->size() > static_cast<std::size_t>(renderer->getMax_textItems()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Mesh>
|
||||
bool printEdgeIds(const Mesh& mesh,
|
||||
TextListItem* eitems,
|
||||
CGAL::Three::Viewer_interface *viewer)
|
||||
{
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::const_type Ppmap;
|
||||
typedef typename boost::property_traits<Ppmap>::value_type Point;
|
||||
typedef typename boost::property_map<Mesh, boost::halfedge_index_t>::type IDmap;
|
||||
|
||||
Ppmap ppmap = get(boost::vertex_point, mesh);
|
||||
IDmap idmap = get(boost::halfedge_index, mesh);
|
||||
TextRenderer *renderer = viewer->textRenderer();
|
||||
const qglviewer::Vec offset = viewer->offset();
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
|
||||
BOOST_FOREACH(typename boost::graph_traits<Mesh>::edge_descriptor e, edges(mesh))
|
||||
{
|
||||
const Point& p1 = get(ppmap, source(e, mesh));
|
||||
const Point& p2 = get(ppmap, target(e, mesh));
|
||||
eitems->append(new TextItem((float)(p1.x() + p2.x()) / 2 + offset.x,
|
||||
(float)(p1.y() + p2.y()) / 2 + offset.y,
|
||||
(float)(p1.z() + p2.z()) / 2 + offset.z,
|
||||
QString("%1").arg(get(idmap, halfedge(e, mesh)) / 2), true, font, Qt::green));
|
||||
}
|
||||
//add the QList to the render's pool
|
||||
renderer->addTextList(eitems);
|
||||
if(eitems->size() > static_cast<std::size_t>(renderer->getMax_textItems()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Mesh>
|
||||
bool printFaceIds(const Mesh& mesh,
|
||||
TextListItem* fitems,
|
||||
CGAL::Three::Viewer_interface *viewer)
|
||||
{
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::const_type Ppmap;
|
||||
typedef typename boost::property_map<Mesh, boost::face_index_t>::type IDmap;
|
||||
|
||||
Ppmap ppmap = get(boost::vertex_point, mesh);
|
||||
IDmap idmap = get(boost::face_index, mesh);
|
||||
TextRenderer *renderer = viewer->textRenderer();
|
||||
const qglviewer::Vec offset = viewer->offset();
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
BOOST_FOREACH(typename boost::graph_traits<Mesh>::face_descriptor fh, faces(mesh))
|
||||
{
|
||||
double x(0), y(0), z(0);
|
||||
int total(0);
|
||||
BOOST_FOREACH(typename boost::graph_traits<Mesh>::vertex_descriptor vh, vertices_around_face(fh->halfedge(), mesh))
|
||||
{
|
||||
x += get(ppmap, vh).x();
|
||||
y += get(ppmap, vh).y();
|
||||
z += get(ppmap, vh).z();
|
||||
++total;
|
||||
}
|
||||
|
||||
fitems->append(new TextItem((float)x / total + offset.x,
|
||||
(float)y / total + offset.y,
|
||||
(float)z / total + offset.z,
|
||||
QString("%1").arg(get(idmap, fh)), true, font, Qt::blue));
|
||||
}
|
||||
//add the QList to the render's pool
|
||||
renderer->addTextList(fitems);
|
||||
if(fitems->size() > static_cast<std::size_t>(renderer->getMax_textItems()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Mesh, typename Point>
|
||||
int zoomToId(const Mesh& mesh,
|
||||
const QString& text,
|
||||
CGAL::Three::Viewer_interface* viewer,
|
||||
typename boost::graph_traits<Mesh>::face_descriptor& selected_fh,
|
||||
Point& p)
|
||||
{
|
||||
typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::const_type Ppmap;
|
||||
typedef typename boost::property_map<Mesh, boost::vertex_index_t>::type VIDmap;
|
||||
typedef typename boost::property_map<Mesh, boost::halfedge_index_t>::type EIDmap;
|
||||
typedef typename boost::property_map<Mesh, boost::face_index_t>::type FIDmap;
|
||||
typedef typename CGAL::Kernel_traits<Point>::Kernel Traits;
|
||||
|
||||
|
||||
Ppmap ppmap = get(boost::vertex_point, mesh);
|
||||
VIDmap vidmap = get(boost::vertex_index, mesh);
|
||||
EIDmap eidmap = get(boost::halfedge_index, mesh);
|
||||
FIDmap fidmap = get(boost::face_index, mesh);
|
||||
|
||||
bool is_int;
|
||||
typename boost::property_traits<VIDmap>::value_type id = text.right(text.length()-1).toUInt(&is_int);
|
||||
QString first = text.left(1);
|
||||
if((first != QString("v") &&
|
||||
first != QString("e") &&
|
||||
first != QString("f")) ||
|
||||
!is_int)
|
||||
{
|
||||
return 1; //("Input must be of the form [v/e/f][int]"
|
||||
}
|
||||
const qglviewer::Vec offset = viewer->offset();
|
||||
typename Traits::Vector_3 normal;
|
||||
if(first == QString("v"))
|
||||
{
|
||||
bool found = false;
|
||||
BOOST_FOREACH(vertex_descriptor vh, vertices(mesh))
|
||||
{
|
||||
if(get(vidmap, vh) == id)
|
||||
{
|
||||
p = Point(get(ppmap, vh).x() + offset.x,
|
||||
get(ppmap, vh).y() + offset.y,
|
||||
get(ppmap, vh).z() + offset.z);
|
||||
selected_fh = face(halfedge(vh, mesh), mesh);
|
||||
normal = CGAL::Polygon_mesh_processing::compute_vertex_normal(vh, mesh);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
return 2;//"No vertex with id %1").arg(id)
|
||||
}
|
||||
}
|
||||
else if(first == QString("e"))
|
||||
{
|
||||
bool found = false;
|
||||
BOOST_FOREACH(typename boost::graph_traits<Mesh>::edge_descriptor e, edges(mesh))
|
||||
{
|
||||
if(get(eidmap, halfedge(e, mesh))/2 == id)
|
||||
{
|
||||
const Point& p1 = get(ppmap, source(e, mesh));
|
||||
const Point& p2 = get(ppmap, target(e, mesh));
|
||||
p = Point((float)(p1.x() + p2.x()) / 2 + offset.x,
|
||||
(float)(p1.y() + p2.y()) / 2 + offset.y,
|
||||
(float)(p1.z() + p2.z()) / 2 + offset.z );
|
||||
typename Traits::Vector_3 normal1 = CGAL::Polygon_mesh_processing::compute_face_normal(face(halfedge(e, mesh),mesh),
|
||||
mesh);
|
||||
typename Traits::Vector_3 normal2 = CGAL::Polygon_mesh_processing::compute_face_normal(face(opposite(halfedge(e, mesh), mesh), mesh),
|
||||
mesh);
|
||||
normal = 0.5*normal1+0.5*normal2;
|
||||
selected_fh = face(halfedge(e, mesh), mesh);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
return 3;//"No edge with id %1").arg(id)
|
||||
}
|
||||
}
|
||||
else if(first == QString("f"))
|
||||
{
|
||||
bool found = false;
|
||||
double x(0), y(0), z(0);
|
||||
int total(0);
|
||||
BOOST_FOREACH(face_descriptor fh, faces(mesh))
|
||||
{
|
||||
if(get(fidmap, fh) != id)
|
||||
continue;
|
||||
BOOST_FOREACH(vertex_descriptor vh, vertices_around_face(halfedge(fh, mesh), mesh))
|
||||
{
|
||||
x+=get(ppmap, vh).x();
|
||||
y+=get(ppmap, vh).y();
|
||||
z+=get(ppmap, vh).z();
|
||||
++total;
|
||||
}
|
||||
p = Point(x/total + offset.x,
|
||||
y/total + offset.y,
|
||||
z/total + offset.z);
|
||||
normal = CGAL::Polygon_mesh_processing::compute_face_normal(
|
||||
fh,
|
||||
mesh);
|
||||
selected_fh = fh;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
return 4; //"No face with id %1").arg(id)
|
||||
}
|
||||
}
|
||||
qglviewer::Quaternion new_orientation(qglviewer::Vec(0,0,-1),
|
||||
qglviewer::Vec(-normal.x(), -normal.y(), -normal.z()));
|
||||
Point new_pos = p +
|
||||
qglviewer::Vec(
|
||||
viewer->camera()->position().x - viewer->camera()->sceneCenter().x,
|
||||
viewer->camera()->position().y - viewer->camera()->sceneCenter().y,
|
||||
viewer->camera()->position().z - viewer->camera()->sceneCenter().z)
|
||||
.norm() * normal ;
|
||||
|
||||
#if QGLVIEWER_VERSION >= 0x020502
|
||||
viewer->camera()->setPivotPoint(qglviewer::Vec(p.x(),
|
||||
p.y(),
|
||||
p.z()));
|
||||
#else
|
||||
viewer->camera()->setRevolveAroundPoint(qglviewer::Vec(p.x(),
|
||||
p.y(),
|
||||
p.z()));
|
||||
#endif
|
||||
|
||||
viewer->moveCameraToCoordinates(QString("%1 %2 %3 %4 %5 %6 %7").arg(new_pos.x())
|
||||
.arg(new_pos.y())
|
||||
.arg(new_pos.z())
|
||||
.arg(new_orientation[0])
|
||||
.arg(new_orientation[1])
|
||||
.arg(new_orientation[2])
|
||||
.arg(new_orientation[3]));
|
||||
viewer->update();
|
||||
return 0; //all clear;
|
||||
}
|
||||
#endif // ID_PRINTING_H
|
||||
|
||||
Loading…
Reference in New Issue