mirror of https://github.com/CGAL/cgal
Merge remote-tracking branch 'cgal/master' into Demo-Multiple_viewers-GF
This commit is contained in:
commit
955053e239
|
|
@ -426,25 +426,7 @@ public:
|
|||
const Local_point& S=facet[id];
|
||||
const Local_point& T=facet[(id+1==facet.size())?0:id+1];
|
||||
Local_vector V1=Local_vector((T-S).x(), (T-S).y(), (T-S).z());
|
||||
if(std::isnan(S.x()) ||
|
||||
std::isnan(S.y()) ||
|
||||
std::isnan(S.z()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(std::isnan(T.x()) ||
|
||||
std::isnan(T.y()) ||
|
||||
std::isnan(T.z()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const Local_point& U=facet[(id+2==facet.size())?0:id+2];
|
||||
if(std::isnan(U.x()) ||
|
||||
std::isnan(U.y()) ||
|
||||
std::isnan(U.z()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const Local_point& U=facet[(id+2>=facet.size())?id+2-facet.size():id+2];
|
||||
Local_vector V2=Local_vector((U-T).x(), (U-T).y(), (U-T).z());
|
||||
|
||||
orientation = Local_kernel::Orientation_3()(V1, V2, normal);
|
||||
|
|
@ -465,7 +447,7 @@ public:
|
|||
const Local_point& T=facet[(id+1==facet.size())?0:id+1];
|
||||
Local_vector V1=Local_vector((T-S).x(), (T-S).y(), (T-S).z());
|
||||
|
||||
const Local_point& U=facet[(id+2==facet.size())?0:id+2];
|
||||
const Local_point& U=facet[(id+2>=facet.size())?id+2-facet.size():id+2];
|
||||
Local_vector V2=Local_vector((U-T).x(), (U-T).y(), (U-T).z());
|
||||
|
||||
local_orientation=Local_kernel::Orientation_3()(V1, V2, normal) ;
|
||||
|
|
|
|||
|
|
@ -740,7 +740,7 @@ protected:
|
|||
setKeyDescription(::Qt::Key_E, "Toggles edges display");
|
||||
setKeyDescription(::Qt::Key_F, "Toggles faces display");
|
||||
setKeyDescription(::Qt::Key_G, "Switch between flat/Gouraud shading display");
|
||||
setKeyDescription(::Qt::Key_M, "Toggles mono color for all faces");
|
||||
setKeyDescription(::Qt::Key_M, "Toggles mono color");
|
||||
setKeyDescription(::Qt::Key_N, "Inverse direction of normals");
|
||||
setKeyDescription(::Qt::Key_V, "Toggles vertices display");
|
||||
setKeyDescription(::Qt::Key_Plus, "Increase size of edges");
|
||||
|
|
@ -935,8 +935,11 @@ protected:
|
|||
}
|
||||
|
||||
virtual QString helpString() const
|
||||
{ return helpString("CGAL Basic Viewer"); }
|
||||
|
||||
virtual QString helpString(const char* title) const
|
||||
{
|
||||
QString text("<h2>C G A L B a s i c V i e w e r</h2>");
|
||||
QString text(QString("<h2>")+QString(title)+QString("</h2>"));
|
||||
text += "Use the mouse to move the camera around the object. ";
|
||||
text += "You can respectively revolve around, zoom and translate with "
|
||||
"the three mouse buttons. ";
|
||||
|
|
@ -966,7 +969,7 @@ protected:
|
|||
return text;
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool m_draw_vertices;
|
||||
bool m_draw_edges;
|
||||
bool m_draw_faces;
|
||||
|
|
|
|||
|
|
@ -21,9 +21,6 @@ if ( LEDA_FOUND AND NOT LEDA_SETUP )
|
|||
link_libraries( ${LEDA_LIBRARIES} )
|
||||
endif()
|
||||
|
||||
if (LEDA_CGAL_FRIEND_INJECTION)
|
||||
message( STATUS "${LEDA_CGAL_FRIEND_INJECTION}" )
|
||||
endif()
|
||||
if (LEDA_CGAL_NO_STRICT_ALIASING)
|
||||
message( STATUS "${LEDA_CGAL_NO_STRICT_ALIASING}" )
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -92,11 +92,6 @@ if ( LEDA_INCLUDE_DIR AND LEDA_LIBRARIES)
|
|||
|
||||
if ( CMAKE_COMPILER_IS_GNUCXX )
|
||||
get_dependency_version (GCC)
|
||||
if ( NOT "${GCC_VERSION}" VERSION_LESS "4.1" )
|
||||
set(LEDA_CGAL_FRIEND_INJECTION TRUE)
|
||||
typed_cache_set( INTERNAL "Add -ffriend-injection on gcc >= 4.1" LEDA_CGAL_FRIEND_INJECTION "Using LEDA with gcc version 4.1 or later: Adding -ffriend-injection")
|
||||
uniquely_add_flags (LEDA_CXX_FLAGS "-ffriend-injection")
|
||||
endif()
|
||||
if ( NOT "${GCC_VERSION}" VERSION_LESS "4.4" )
|
||||
set(LEDA_CGAL_NO_STRICT_ALIASING TRUE)
|
||||
typed_cache_set( INTERNAL "Add -fno-strict-aliasing on gcc >= 4.4" LEDA_CGAL_NO_STRICT_ALIASING "Using LEDA with gcc version 4.4 or later: Adding -fno-strict-aliasing")
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ if ( NOT (CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND ) )
|
|||
|
||||
else()
|
||||
|
||||
add_definitions(-DQT_NO_KEYWORDS)
|
||||
add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS)
|
||||
|
||||
# ui file, created wih Qt Designer
|
||||
qt5_wrap_ui(uis MainWindow.ui CreateMesh.ui CreateMenger.ui
|
||||
|
|
@ -64,7 +64,7 @@ add_executable(Linear_cell_complex_3_demo
|
|||
|
||||
add_to_cached_list(CGAL_EXECUTABLE_TARGETS Linear_cell_complex_3_demo)
|
||||
|
||||
target_link_libraries(Linear_cell_complex_3_demo PRIVATE
|
||||
target_link_libraries(Linear_cell_complex_3_demo PUBLIC
|
||||
CGAL::CGAL CGAL::CGAL_Qt5 Qt5::Gui Qt5::OpenGL)
|
||||
|
||||
include(${CGAL_MODULES_DIR}/CGAL_add_test.cmake)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ void subdivide_lcc_pqq (LCC & m);
|
|||
|
||||
#define DELAY_STATUSMSG 1500
|
||||
|
||||
MainWindow::MainWindow (QWidget * parent):CGAL::Qt::DemosMainWindow (parent),
|
||||
MainWindow::MainWindow (QWidget * parent) : CGAL::Qt::DemosMainWindow (parent),
|
||||
nbcube (0),
|
||||
dialogmesh (this),
|
||||
dialogmenger(this),
|
||||
|
|
@ -78,7 +78,7 @@ MainWindow::MainWindow (QWidget * parent):CGAL::Qt::DemosMainWindow (parent),
|
|||
|
||||
QObject::connect(&dialogmesh, SIGNAL(accepted()),
|
||||
this, SLOT(onCreateMeshOk()));
|
||||
this->viewer->setScene(&scene);
|
||||
this->viewer->setScene(&scene, false);
|
||||
|
||||
connect_actions ();
|
||||
this->addAboutDemo (":/cgal/help/about_Linear_cell_complex_3.html");
|
||||
|
|
|
|||
|
|
@ -19,928 +19,44 @@
|
|||
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
|
||||
// Contributor(s): Kumar Snehasish <kumar.snehasish@gmail.com>
|
||||
//
|
||||
|
||||
#include "Viewer.h"
|
||||
|
||||
#include <CGAL/Linear_cell_complex_operations.h>
|
||||
#include <CGAL/bounding_box.h>
|
||||
#include <CGAL/Qt/CreateOpenGLContext.h>
|
||||
#include <CGAL/Qt/viewer_actions.h>
|
||||
|
||||
#include <CGAL/Qt/vec.h>
|
||||
#include <QDebug>
|
||||
|
||||
//Vertex source code
|
||||
const char vertex_source[] =
|
||||
{
|
||||
"#version 120 \n"
|
||||
"attribute highp vec4 vertex;\n"
|
||||
"attribute highp vec3 normal;\n"
|
||||
"attribute highp vec3 color;\n"
|
||||
Viewer::Viewer(QWidget* parent) :
|
||||
Base(parent, NULL, ""),
|
||||
m_previous_scene_empty(true)
|
||||
{}
|
||||
|
||||
"uniform highp mat4 mvp_matrix;\n"
|
||||
"uniform highp mat4 mv_matrix; \n"
|
||||
"uniform highp float point_size; \n"
|
||||
|
||||
"varying highp vec4 fP; \n"
|
||||
"varying highp vec3 fN; \n"
|
||||
"varying highp vec4 fColor; \n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" gl_PointSize = point_size; \n"
|
||||
" fP = mv_matrix * vertex; \n"
|
||||
" fN = mat3(mv_matrix)* normal; \n"
|
||||
" fColor = vec4(color, 1.0); \n"
|
||||
" gl_Position = mvp_matrix * vertex;\n"
|
||||
"}"
|
||||
};
|
||||
|
||||
//Vertex source code
|
||||
const char fragment_source[] =
|
||||
{
|
||||
"#version 120 \n"
|
||||
"varying highp vec4 fP; \n"
|
||||
"varying highp vec3 fN; \n"
|
||||
"varying highp vec4 fColor; \n"
|
||||
"uniform vec4 light_pos; \n"
|
||||
"uniform vec4 light_diff; \n"
|
||||
"uniform vec4 light_spec; \n"
|
||||
"uniform vec4 light_amb; \n"
|
||||
"uniform float spec_power ; \n"
|
||||
|
||||
"void main(void) { \n"
|
||||
|
||||
" vec3 L = light_pos.xyz - fP.xyz; \n"
|
||||
" vec3 V = -fP.xyz; \n"
|
||||
|
||||
" vec3 N = normalize(fN); \n"
|
||||
" L = normalize(L); \n"
|
||||
" V = normalize(V); \n"
|
||||
|
||||
" vec3 R = reflect(-L, N); \n"
|
||||
" vec4 diffuse = max(dot(N,L), 0.0) * light_diff * fColor; \n"
|
||||
" vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; \n"
|
||||
|
||||
"gl_FragColor = light_amb*fColor + diffuse ; \n"
|
||||
"} \n"
|
||||
"\n"
|
||||
};
|
||||
|
||||
//Vertex source code
|
||||
const char vertex_source_p_l[] =
|
||||
{
|
||||
"#version 120 \n"
|
||||
"attribute highp vec4 vertex;\n"
|
||||
"uniform highp mat4 mvp_matrix;\n"
|
||||
"uniform highp float point_size; \n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" gl_PointSize = point_size; \n"
|
||||
" gl_Position = mvp_matrix * vertex;\n"
|
||||
"}"
|
||||
};
|
||||
//Vertex source code
|
||||
const char fragment_source_p_l[] =
|
||||
{
|
||||
"#version 120 \n"
|
||||
"uniform highp vec4 color; \n"
|
||||
"void main(void) { \n"
|
||||
"gl_FragColor = color; \n"
|
||||
"} \n"
|
||||
"\n"
|
||||
};
|
||||
|
||||
Viewer::Viewer(QWidget* parent)
|
||||
: CGAL::QGLViewer(parent),
|
||||
wireframe(false),
|
||||
flatShading(true),
|
||||
edges(true),
|
||||
vertices(true),
|
||||
inverse_normal(false),
|
||||
size_points(7.),
|
||||
size_edges(3.1),
|
||||
ambient(0.6f, 0.5f, 0.5f, 0.5f),
|
||||
m_previous_scene_empty(true),
|
||||
are_buffers_initialized(false)
|
||||
void Viewer::setScene(Scene* scene_, bool doredraw)
|
||||
{
|
||||
}
|
||||
|
||||
Viewer::~Viewer()
|
||||
{
|
||||
for (int i=0; i<NB_VBO_BUFFERS; ++i)
|
||||
buffers[i].destroy();
|
||||
|
||||
for (int i=0; i<NB_VAO_BUFFERS; ++i)
|
||||
vao[i].destroy();
|
||||
}
|
||||
|
||||
void Viewer::compile_shaders()
|
||||
{
|
||||
rendering_program.removeAllShaders();
|
||||
rendering_program_p_l.removeAllShaders();
|
||||
|
||||
// Create the buffers
|
||||
for (int i=0; i<NB_VBO_BUFFERS; ++i)
|
||||
if(!buffers[i].isCreated() && !buffers[i].create())
|
||||
{
|
||||
std::cerr<<"VBO Creation number "<<i<<" FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
for (int i=0; i<NB_VAO_BUFFERS; ++i)
|
||||
if(!vao[i].isCreated() && !vao[i].create())
|
||||
{
|
||||
std::cerr<<"VAO Creation number "<<i<<" FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
//The Facets
|
||||
QOpenGLShader *vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex);
|
||||
if(!vertex_shader->compileSourceCode(vertex_source))
|
||||
{
|
||||
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
QOpenGLShader *fragment_shader= new QOpenGLShader(QOpenGLShader::Fragment);
|
||||
if(!fragment_shader->compileSourceCode(fragment_source))
|
||||
{
|
||||
std::cerr<<"Compiling fragmentsource FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
if(!rendering_program.addShader(vertex_shader))
|
||||
{
|
||||
std::cerr<<"adding vertex shader FAILED"<<std::endl;
|
||||
}
|
||||
if(!rendering_program.addShader(fragment_shader))
|
||||
{
|
||||
std::cerr<<"adding fragment shader FAILED"<<std::endl;
|
||||
}
|
||||
if(!rendering_program.link())
|
||||
{
|
||||
std::cerr<<"linking Program FAILED"<<std::endl;
|
||||
}
|
||||
rendering_program.bind();
|
||||
|
||||
vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex);
|
||||
if(!vertex_shader->compileSourceCode(vertex_source_p_l))
|
||||
{
|
||||
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
fragment_shader= new QOpenGLShader(QOpenGLShader::Fragment);
|
||||
if(!fragment_shader->compileSourceCode(fragment_source_p_l))
|
||||
{
|
||||
std::cerr<<"Compiling fragmentsource FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
if(!rendering_program_p_l.addShader(vertex_shader))
|
||||
{
|
||||
std::cerr<<"adding vertex shader FAILED"<<std::endl;
|
||||
}
|
||||
if(!rendering_program_p_l.addShader(fragment_shader))
|
||||
{
|
||||
std::cerr<<"adding fragment shader FAILED"<<std::endl;
|
||||
}
|
||||
if(!rendering_program_p_l.link())
|
||||
{
|
||||
std::cerr<<"linking Program FAILED"<<std::endl;
|
||||
}
|
||||
rendering_program_p_l.bind();
|
||||
}
|
||||
|
||||
void Viewer::initialize_buffers()
|
||||
{
|
||||
//points of the facets
|
||||
vao[0].bind();
|
||||
buffers[0].bind();
|
||||
buffers[0].allocate(pos_facets.data(),
|
||||
static_cast<int>(pos_facets.size()*sizeof(float)));
|
||||
vertexLocation[0] = rendering_program.attributeLocation("vertex");
|
||||
rendering_program.bind();
|
||||
rendering_program.enableAttributeArray(vertexLocation[0]);
|
||||
rendering_program.setAttributeBuffer(vertexLocation[0],GL_FLOAT,0,3);
|
||||
rendering_program.release();
|
||||
buffers[0].release();
|
||||
|
||||
//normals of the facets
|
||||
buffers[1].bind();
|
||||
buffers[1].allocate(flat_normals.data(),
|
||||
static_cast<int>(flat_normals.size()*sizeof(float)));
|
||||
normalsLocation = rendering_program.attributeLocation("normal");
|
||||
rendering_program.bind();
|
||||
rendering_program.enableAttributeArray(normalsLocation);
|
||||
rendering_program.setAttributeBuffer(normalsLocation,GL_FLOAT,0,3);
|
||||
buffers[1].release();
|
||||
|
||||
//colors of the facets
|
||||
buffers[2].bind();
|
||||
buffers[2].allocate(colors.data(),
|
||||
static_cast<int>(colors.size()*sizeof(float)));
|
||||
colorsLocation = rendering_program.attributeLocation("color");
|
||||
rendering_program.bind();
|
||||
rendering_program.enableAttributeArray(colorsLocation);
|
||||
rendering_program.setAttributeBuffer(colorsLocation,GL_FLOAT,0,3);
|
||||
buffers[2].release();
|
||||
rendering_program.release();
|
||||
|
||||
vao[0].release();
|
||||
vao[1].bind();
|
||||
|
||||
//points of the facets
|
||||
buffers[3].bind();
|
||||
buffers[3].allocate(pos_facets.data(), static_cast<int>(pos_facets.size()*sizeof(float)));
|
||||
vertexLocation[0] = rendering_program.attributeLocation("vertex");
|
||||
rendering_program.bind();
|
||||
rendering_program.enableAttributeArray(vertexLocation[0]);
|
||||
rendering_program.setAttributeBuffer(vertexLocation[0],GL_FLOAT,0,3);
|
||||
rendering_program.release();
|
||||
buffers[3].release();
|
||||
|
||||
//normals of the facets
|
||||
buffers[4].bind();
|
||||
buffers[4].allocate(smooth_normals.data(),
|
||||
static_cast<int>(smooth_normals.size()*sizeof(float)));
|
||||
normalsLocation = rendering_program.attributeLocation("normal");
|
||||
rendering_program.bind();
|
||||
rendering_program.enableAttributeArray(normalsLocation);
|
||||
rendering_program.setAttributeBuffer(normalsLocation,GL_FLOAT,0,3);
|
||||
buffers[4].release();
|
||||
|
||||
//colors of the facets
|
||||
buffers[5].bind();
|
||||
buffers[5].allocate(colors.data(), static_cast<int>(colors.size()*sizeof(float)));
|
||||
colorsLocation = rendering_program.attributeLocation("color");
|
||||
rendering_program.bind();
|
||||
rendering_program.enableAttributeArray(colorsLocation);
|
||||
rendering_program.setAttributeBuffer(colorsLocation,GL_FLOAT,0,3);
|
||||
buffers[5].release();
|
||||
rendering_program.release();
|
||||
|
||||
vao[1].release();
|
||||
|
||||
//The lines
|
||||
vao[2].bind();
|
||||
buffers[6].bind();
|
||||
buffers[6].allocate(pos_lines.data(), static_cast<int>(pos_lines.size()*sizeof(float)));
|
||||
vertexLocation[2] = rendering_program_p_l.attributeLocation("vertex");
|
||||
rendering_program_p_l.bind();
|
||||
rendering_program_p_l.enableAttributeArray(vertexLocation[2]);
|
||||
rendering_program_p_l.setAttributeBuffer(vertexLocation[2],GL_FLOAT,0,3);
|
||||
buffers[6].release();
|
||||
rendering_program_p_l.release();
|
||||
vao[2].release();
|
||||
|
||||
//The points
|
||||
vao[3].bind();
|
||||
buffers[7].bind();
|
||||
buffers[7].allocate(pos_points.data(), static_cast<int>(pos_points.size()*sizeof(float)));
|
||||
vertexLocation[2] = rendering_program_p_l.attributeLocation("vertex");
|
||||
rendering_program_p_l.bind();
|
||||
rendering_program_p_l.enableAttributeArray(vertexLocation[2]);
|
||||
rendering_program_p_l.setAttributeBuffer(vertexLocation[2],GL_FLOAT,0,3);
|
||||
buffers[7].release();
|
||||
rendering_program_p_l.release();
|
||||
vao[3].release();
|
||||
|
||||
are_buffers_initialized = true;
|
||||
}
|
||||
|
||||
void Viewer::compute_face(Dart_handle dh, LCC::size_type markface)
|
||||
{
|
||||
LCC &lcc = *scene->lcc;
|
||||
|
||||
CGAL::mark_cell<LCC, 2>(lcc, dh, markface);
|
||||
|
||||
double r = (double)lcc.info<3>(dh).color().r()/255.0;
|
||||
double g = (double)lcc.info<3>(dh).color().g()/255.0;
|
||||
double b = (double)lcc.info<3>(dh).color().b()/255.0;
|
||||
if ( !lcc.is_free(dh, 3) )
|
||||
{
|
||||
r += (double)lcc.info<3>(lcc.beta(dh,3)).color().r()/255.0;
|
||||
g += (double)lcc.info<3>(lcc.beta(dh,3)).color().g()/255.0;
|
||||
b += (double)lcc.info<3>(lcc.beta(dh,3)).color().b()/255.0;
|
||||
r /= 2; g /= 2; b /= 2;
|
||||
}
|
||||
|
||||
//compute flat normals
|
||||
LCC::Vector normal = CGAL::compute_normal_of_cell_2(lcc,dh);
|
||||
normal = normal/(CGAL::sqrt(normal*normal));
|
||||
if (inverse_normal)
|
||||
normal=normal*-1;
|
||||
|
||||
if (lcc.beta<1,1,1>(dh)!=dh)
|
||||
{
|
||||
try // Try catch to avoir crash of triangulation
|
||||
{
|
||||
P_traits cdt_traits(normal);
|
||||
CDT cdt(cdt_traits);
|
||||
|
||||
// Iterates on the vector of facet handles
|
||||
CDT::Vertex_handle previous = NULL, first = NULL;
|
||||
for (LCC::Dart_of_orbit_range<1>::const_iterator
|
||||
he_circ = lcc.darts_of_orbit<1>(dh).begin(),
|
||||
he_circ_end = lcc.darts_of_orbit<1>(dh).end();
|
||||
he_circ!=he_circ_end; ++he_circ)
|
||||
{
|
||||
CDT::Vertex_handle vh = cdt.insert(lcc.point(he_circ));
|
||||
if(first == NULL)
|
||||
{ first = vh; }
|
||||
vh->info().v = CGAL::compute_normal_of_cell_0<LCC>(lcc, he_circ);
|
||||
if (inverse_normal) vh->info().v=vh->info().v*-1;
|
||||
if(previous!=NULL && previous != vh)
|
||||
{ cdt.insert_constraint(previous, vh); }
|
||||
previous = vh;
|
||||
}
|
||||
if (previous!=NULL)
|
||||
cdt.insert_constraint(previous, first);
|
||||
|
||||
// sets mark is_external
|
||||
for(CDT::All_faces_iterator fit = cdt.all_faces_begin(),
|
||||
fitend = cdt.all_faces_end(); fit!=fitend; ++fit)
|
||||
{
|
||||
fit->info().is_external = true;
|
||||
fit->info().is_process = false;
|
||||
}
|
||||
//check if the facet is external or internal
|
||||
std::queue<CDT::Face_handle> face_queue;
|
||||
CDT::Face_handle face_internal = NULL;
|
||||
face_queue.push(cdt.infinite_vertex()->face());
|
||||
while(! face_queue.empty() )
|
||||
{
|
||||
CDT::Face_handle fh = face_queue.front();
|
||||
face_queue.pop();
|
||||
if(!fh->info().is_process)
|
||||
{
|
||||
fh->info().is_process = true;
|
||||
for(int i = 0; i <3; ++i)
|
||||
{
|
||||
if(!cdt.is_constrained(std::make_pair(fh, i)))
|
||||
{
|
||||
face_queue.push(fh->neighbor(i));
|
||||
}
|
||||
else if (face_internal==NULL)
|
||||
{
|
||||
face_internal = fh->neighbor(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( face_internal!=NULL )
|
||||
face_queue.push(face_internal);
|
||||
|
||||
while(! face_queue.empty() )
|
||||
{
|
||||
CDT::Face_handle fh = face_queue.front();
|
||||
face_queue.pop();
|
||||
if(!fh->info().is_process)
|
||||
{
|
||||
fh->info().is_process = true;
|
||||
fh->info().is_external = false;
|
||||
for(int i = 0; i <3; ++i)
|
||||
{
|
||||
if(!cdt.is_constrained(std::make_pair(fh, i)))
|
||||
{
|
||||
face_queue.push(fh->neighbor(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//iterates on the internal faces to add the vertices to the positions
|
||||
//and the normals to the appropriate vectors
|
||||
for(CDT::Finite_faces_iterator ffit = cdt.finite_faces_begin(),
|
||||
ffitend = cdt.finite_faces_end(); ffit != ffitend; ++ffit)
|
||||
{
|
||||
if(!ffit->info().is_external)
|
||||
{
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
smooth_normals.push_back(ffit->vertex(0)->info().v.x());
|
||||
smooth_normals.push_back(ffit->vertex(0)->info().v.y());
|
||||
smooth_normals.push_back(ffit->vertex(0)->info().v.z());
|
||||
|
||||
smooth_normals.push_back(ffit->vertex(1)->info().v.x());
|
||||
smooth_normals.push_back(ffit->vertex(1)->info().v.y());
|
||||
smooth_normals.push_back(ffit->vertex(1)->info().v.z());
|
||||
|
||||
smooth_normals.push_back(ffit->vertex(2)->info().v.x());
|
||||
smooth_normals.push_back(ffit->vertex(2)->info().v.y());
|
||||
smooth_normals.push_back(ffit->vertex(2)->info().v.z());
|
||||
|
||||
pos_facets.push_back(ffit->vertex(0)->point().x());
|
||||
pos_facets.push_back(ffit->vertex(0)->point().y());
|
||||
pos_facets.push_back(ffit->vertex(0)->point().z());
|
||||
|
||||
pos_facets.push_back(ffit->vertex(1)->point().x());
|
||||
pos_facets.push_back(ffit->vertex(1)->point().y());
|
||||
pos_facets.push_back(ffit->vertex(1)->point().z());
|
||||
|
||||
pos_facets.push_back(ffit->vertex(2)->point().x());
|
||||
pos_facets.push_back(ffit->vertex(2)->point().y());
|
||||
pos_facets.push_back(ffit->vertex(2)->point().z());
|
||||
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{ // Triangulation crash: the face is not filled
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // The face is a triangle
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
for (LCC::Dart_of_orbit_range<1>::const_iterator
|
||||
orbitIter = lcc.darts_of_orbit<1>(dh).begin();
|
||||
orbitIter.cont(); ++orbitIter)
|
||||
{
|
||||
//compute Smooth normals
|
||||
LCC::Vector normal = CGAL::compute_normal_of_cell_0(lcc,orbitIter);
|
||||
normal = normal/(CGAL::sqrt(normal*normal));
|
||||
if (inverse_normal) normal=normal*-1;
|
||||
|
||||
smooth_normals.push_back(normal.x());
|
||||
smooth_normals.push_back(normal.y());
|
||||
smooth_normals.push_back(normal.z());
|
||||
|
||||
const LCC::Point& p = lcc.point(orbitIter);
|
||||
pos_facets.push_back(p.x());
|
||||
pos_facets.push_back(p.y());
|
||||
pos_facets.push_back(p.z());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Viewer::compute_edge(Dart_handle dh, LCC::size_type markedge)
|
||||
{
|
||||
LCC &lcc = *scene->lcc;
|
||||
|
||||
CGAL::mark_cell<LCC, 1>(lcc, dh, markedge);
|
||||
|
||||
const LCC::Point& p = lcc.point(dh);
|
||||
Dart_handle d2 = lcc.other_extremity(dh);
|
||||
if ( d2!=NULL )
|
||||
{
|
||||
const LCC::Point& p2 = lcc.point(d2);
|
||||
pos_lines.push_back(p.x());
|
||||
pos_lines.push_back(p.y());
|
||||
pos_lines.push_back(p.z());
|
||||
|
||||
pos_lines.push_back(p2.x());
|
||||
pos_lines.push_back(p2.y());
|
||||
pos_lines.push_back(p2.z());
|
||||
}
|
||||
}
|
||||
|
||||
void Viewer::compute_vertex(Dart_handle dh, LCC::size_type markvertex, bool& empty)
|
||||
{
|
||||
LCC &lcc = *scene->lcc;
|
||||
|
||||
CGAL::mark_cell<LCC, 0>(lcc, dh, markvertex);
|
||||
|
||||
const LCC::Point& p = lcc.point(dh);
|
||||
pos_points.push_back(p.x());
|
||||
pos_points.push_back(p.y());
|
||||
pos_points.push_back(p.z());
|
||||
|
||||
if ( empty )
|
||||
{
|
||||
bb = p.bbox();
|
||||
empty = false;
|
||||
}
|
||||
else
|
||||
bb = bb + p.bbox();
|
||||
}
|
||||
|
||||
void Viewer::compute_elements()
|
||||
{
|
||||
LCC &lcc = *scene->lcc;
|
||||
|
||||
pos_facets.clear();
|
||||
flat_normals.clear();
|
||||
smooth_normals.clear();
|
||||
colors.clear();
|
||||
pos_lines.clear();
|
||||
pos_points.clear();
|
||||
|
||||
if ( lcc.is_empty() )
|
||||
{
|
||||
bb = LCC::Point(CGAL::ORIGIN).bbox();
|
||||
bb = bb + LCC::Point(1,1,1).bbox(); // To avoid a warning from Qglviewer
|
||||
return;
|
||||
}
|
||||
|
||||
LCC::size_type markvertex = lcc.get_new_mark();
|
||||
LCC::size_type markedge = lcc.get_new_mark();
|
||||
LCC::size_type markface = lcc.get_new_mark();
|
||||
|
||||
bool empty = true;
|
||||
for (LCC::Attribute_range<3>::type::iterator it=lcc.attributes<3>().begin(),
|
||||
itend=lcc.attributes<3>().end(); it!=itend; ++it )
|
||||
{
|
||||
if ( it->info().is_visible() )
|
||||
{
|
||||
for(LCC::Dart_of_cell_range<3>::iterator
|
||||
dartIter=lcc.darts_of_cell<3>(lcc.dart_of_attribute<3>(it)).begin();
|
||||
dartIter.cont(); ++dartIter)
|
||||
{
|
||||
if ( it->info().is_filled() && !lcc.is_marked(dartIter, markface) )
|
||||
compute_face(dartIter, markface);
|
||||
|
||||
if ( !lcc.is_marked(dartIter, markedge) )
|
||||
compute_edge(dartIter, markedge);
|
||||
|
||||
if ( !lcc.is_marked(dartIter, markvertex) )
|
||||
compute_vertex(dartIter, markvertex, empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty )
|
||||
{
|
||||
bb = LCC::Point(CGAL::ORIGIN).bbox();
|
||||
bb = bb + LCC::Point(1,1,1).bbox(); // To avoid a warning from Qglviewer
|
||||
}
|
||||
|
||||
for (LCC::Dart_range::iterator it=lcc.darts().begin(),
|
||||
itend=lcc.darts().end(); it!=itend; ++it )
|
||||
{
|
||||
lcc.unmark(it, markvertex);
|
||||
lcc.unmark(it, markedge);
|
||||
lcc.unmark(it, markface);
|
||||
}
|
||||
|
||||
lcc.free_mark(markvertex);
|
||||
lcc.free_mark(markedge);
|
||||
lcc.free_mark(markface);
|
||||
}
|
||||
|
||||
void Viewer::attrib_buffers(CGAL::QGLViewer* viewer)
|
||||
{
|
||||
QMatrix4x4 mvpMatrix;
|
||||
QMatrix4x4 mvMatrix;
|
||||
double mat[16];
|
||||
viewer->camera()->getModelViewProjectionMatrix(mat);
|
||||
for(int i=0; i < 16; i++)
|
||||
{
|
||||
mvpMatrix.data()[i] = (float)mat[i];
|
||||
}
|
||||
viewer->camera()->getModelViewMatrix(mat);
|
||||
for(int i=0; i < 16; i++)
|
||||
{
|
||||
mvMatrix.data()[i] = (float)mat[i];
|
||||
}
|
||||
// define material
|
||||
QVector4D diffuse( 0.9f,
|
||||
0.9f,
|
||||
0.9f,
|
||||
0.9f );
|
||||
|
||||
QVector4D specular( 0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f );
|
||||
|
||||
|
||||
QVector4D position((bb.xmax()-bb.xmin())/2, (bb.ymax()-bb.ymin())/2,bb.zmax(), 0.0 );
|
||||
GLfloat shininess = 1.0f;
|
||||
|
||||
rendering_program.bind();
|
||||
mvpLocation[0] = rendering_program.uniformLocation("mvp_matrix");
|
||||
mvLocation = rendering_program.uniformLocation("mv_matrix");
|
||||
lightLocation[0] = rendering_program.uniformLocation("light_pos");
|
||||
lightLocation[1] = rendering_program.uniformLocation("light_diff");
|
||||
lightLocation[2] = rendering_program.uniformLocation("light_spec");
|
||||
lightLocation[3] = rendering_program.uniformLocation("light_amb");
|
||||
lightLocation[4] = rendering_program.uniformLocation("spec_power");
|
||||
|
||||
rendering_program.setUniformValue(lightLocation[0], position);
|
||||
rendering_program.setUniformValue(lightLocation[1], diffuse);
|
||||
rendering_program.setUniformValue(lightLocation[2], specular);
|
||||
rendering_program.setUniformValue(lightLocation[3], ambient);
|
||||
rendering_program.setUniformValue(lightLocation[4], shininess);
|
||||
rendering_program.setUniformValue(mvpLocation[0], mvpMatrix);
|
||||
rendering_program.setUniformValue(mvLocation, mvMatrix);
|
||||
|
||||
rendering_program.release();
|
||||
rendering_program_p_l.bind();
|
||||
mvpLocation[1] = rendering_program_p_l.uniformLocation("mvp_matrix");
|
||||
colorLocation = rendering_program_p_l.uniformLocation("color");
|
||||
rendering_program.setUniformValue(mvpLocation[1], mvpMatrix);
|
||||
rendering_program_p_l.release();
|
||||
scene = scene_;
|
||||
set_lcc(scene->lcc, doredraw);
|
||||
}
|
||||
|
||||
void Viewer::sceneChanged()
|
||||
{
|
||||
compute_elements();
|
||||
this->camera()->setSceneBoundingBox(CGAL::qglviewer::Vec(bb.xmin(),
|
||||
bb.ymin(),
|
||||
bb.zmin()),
|
||||
CGAL::qglviewer::Vec(bb.xmax(),
|
||||
bb.ymax(),
|
||||
bb.zmax()));
|
||||
are_buffers_initialized = false;
|
||||
|
||||
Base::compute_elements();
|
||||
this->camera()->
|
||||
setSceneBoundingBox(CGAL::qglviewer::Vec(m_bounding_box.xmin(),
|
||||
m_bounding_box.ymin(),
|
||||
m_bounding_box.zmin()),
|
||||
CGAL::qglviewer::Vec(m_bounding_box.xmax(),
|
||||
m_bounding_box.ymax(),
|
||||
m_bounding_box.zmax()));
|
||||
Base::redraw();
|
||||
if (m_previous_scene_empty)
|
||||
this->showEntireScene();
|
||||
else
|
||||
this->update();
|
||||
{ this->showEntireScene(); }
|
||||
|
||||
m_previous_scene_empty = scene->lcc->is_empty(); // for the next call to sceneChanged
|
||||
}
|
||||
|
||||
void Viewer::draw()
|
||||
{
|
||||
if(scene)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
if(!are_buffers_initialized)
|
||||
initialize_buffers();
|
||||
|
||||
QColor color;
|
||||
if ( !wireframe )
|
||||
{
|
||||
if(flatShading)
|
||||
{
|
||||
vao[0].bind();
|
||||
attrib_buffers(this);
|
||||
rendering_program.bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(pos_facets.size()/3));
|
||||
rendering_program.release();
|
||||
vao[0].release();
|
||||
}
|
||||
else
|
||||
{
|
||||
vao[1].bind();
|
||||
attrib_buffers(this);
|
||||
rendering_program.bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(pos_facets.size()/3));
|
||||
rendering_program.release();
|
||||
vao[1].release();
|
||||
}
|
||||
}
|
||||
if(edges)
|
||||
{
|
||||
vao[2].bind();
|
||||
attrib_buffers(this);
|
||||
color.setRgbF(0.2f, 0.2f, 0.7f);
|
||||
rendering_program_p_l.bind();
|
||||
rendering_program_p_l.setAttributeValue(colorLocation,color);
|
||||
glLineWidth(size_edges);
|
||||
glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(pos_lines.size()/3));
|
||||
rendering_program_p_l.release();
|
||||
vao[2].release();
|
||||
}
|
||||
if(vertices)
|
||||
{
|
||||
vao[3].bind();
|
||||
attrib_buffers(this);
|
||||
color.setRgbF(.2f,.2f,.6f);
|
||||
rendering_program_p_l.bind();
|
||||
rendering_program_p_l.setAttributeValue(colorLocation,color);
|
||||
rendering_program_p_l.setUniformValue("point_size", GLfloat(size_points));
|
||||
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(pos_points.size()/3));
|
||||
rendering_program_p_l.release();
|
||||
vao[3].release();
|
||||
}
|
||||
}
|
||||
}
|
||||
void Viewer::init()
|
||||
{
|
||||
// Restore previous viewer state.
|
||||
restoreStateFromFile();
|
||||
initializeOpenGLFunctions();
|
||||
// Define 'Control+Q' as the new exit shortcut (default was 'Escape')
|
||||
setShortcut(CGAL::qglviewer::EXIT_VIEWER, Qt::CTRL+Qt::Key_Q);
|
||||
|
||||
// Add custom key description (see keyPressEvent).
|
||||
setKeyDescription(Qt::Key_W, "Toggles wire frame display");
|
||||
setKeyDescription(Qt::Key_F, "Toggles flat shading display");
|
||||
setKeyDescription(Qt::Key_E, "Toggles edges display");
|
||||
setKeyDescription(Qt::Key_V, "Toggles vertices display");
|
||||
setKeyDescription(Qt::Key_N, "Inverse direction of normals");
|
||||
setKeyDescription(Qt::Key_Plus, "Increase size of edges");
|
||||
setKeyDescription(Qt::Key_Minus, "Decrease size of edges");
|
||||
setKeyDescription(Qt::Key_Plus+Qt::ShiftModifier, "Increase size of vertices");
|
||||
setKeyDescription(Qt::Key_Minus+Qt::ShiftModifier, "Decrease size of vertices");
|
||||
setKeyDescription(Qt::Key_PageDown, "Increase light (all colors, use shift/alt/ctrl for one rgb component)");
|
||||
setKeyDescription(Qt::Key_PageUp, "Decrease light (all colors, use shift/alt/ctrl for one rgb component)");
|
||||
|
||||
// Light default parameters
|
||||
glLineWidth(size_edges);
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(1.0f,1.0f);
|
||||
glClearColor(1.0f,1.0f,1.0f,0.0f);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glDisable(GL_POLYGON_SMOOTH_HINT);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
|
||||
compile_shaders();
|
||||
}
|
||||
|
||||
void Viewer::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
const Qt::KeyboardModifiers modifiers = e->modifiers();
|
||||
|
||||
if ((e->key()==Qt::Key_W) && (modifiers==Qt::NoButton))
|
||||
{
|
||||
wireframe = !wireframe;
|
||||
if (wireframe)
|
||||
{
|
||||
displayMessage("Wireframe.");
|
||||
}
|
||||
else
|
||||
{
|
||||
displayMessage("Filled faces.");
|
||||
}
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_F) && (modifiers==Qt::NoButton))
|
||||
{
|
||||
flatShading = !flatShading;
|
||||
if (flatShading)
|
||||
displayMessage("Flat shading.");
|
||||
else
|
||||
displayMessage("Gouraud shading.");
|
||||
|
||||
update();
|
||||
|
||||
}
|
||||
else if ((e->key()==Qt::Key_E) && (modifiers==Qt::NoButton))
|
||||
{
|
||||
edges = !edges;
|
||||
displayMessage(QString("Draw edges=%1.").arg(edges?"true":"false"));
|
||||
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_V) && (modifiers==Qt::NoButton))
|
||||
{
|
||||
vertices = !vertices;
|
||||
displayMessage(QString("Draw vertices=%1.").arg(vertices?"true":"false"));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_N) && (modifiers==Qt::NoButton))
|
||||
{
|
||||
inverse_normal = !inverse_normal;
|
||||
displayMessage(QString("Inverse normal=%1.").arg(inverse_normal?"true":"false"));
|
||||
sceneChanged();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_Plus) && (modifiers==Qt::KeypadModifier))
|
||||
{
|
||||
size_edges+=.5;
|
||||
displayMessage(QString("Size of edges=%1.").arg(size_edges));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_Minus) && (modifiers==Qt::KeypadModifier))
|
||||
{
|
||||
if (size_edges>.5) size_edges-=.5;
|
||||
displayMessage(QString("Size of edges=%1.").arg(size_edges));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_Plus) && (modifiers==(Qt::ShiftModifier|Qt::KeypadModifier)))
|
||||
{
|
||||
size_points+=.5;
|
||||
displayMessage(QString("Size of points=%1.").arg(size_points));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_Minus) && (modifiers==(Qt::ShiftModifier|Qt::KeypadModifier)))
|
||||
{
|
||||
if (size_points>.5) size_points-=.5;
|
||||
displayMessage(QString("Size of points=%1.").arg(size_points));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton))
|
||||
{
|
||||
ambient.setX(ambient.x()+.1);
|
||||
if (ambient.x()>1.) ambient.setX(1.);
|
||||
ambient.setY(ambient.x()+.1);
|
||||
if (ambient.y()>1.) ambient.setY(1.);
|
||||
ambient.setZ(ambient.x()+.1);
|
||||
if (ambient.z()>1.) ambient.setZ(1.);
|
||||
displayMessage(QString("Light color=(%1 %2 %3).").
|
||||
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_PageDown) && (modifiers==Qt::NoButton))
|
||||
{
|
||||
ambient.setX(ambient.x()-.1);
|
||||
if (ambient.x()<0.) ambient.setX(0.);
|
||||
ambient.setY(ambient.y()-.1);
|
||||
if (ambient.y()<0.) ambient.setY(0.);
|
||||
ambient.setZ(ambient.z()-.1);
|
||||
if (ambient.z()<0.) ambient.setZ(0.);
|
||||
displayMessage(QString("Light color=(%1 %2 %3).").
|
||||
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::ShiftModifier))
|
||||
{
|
||||
ambient.setX(ambient.x()+.1);
|
||||
if (ambient.x()>1.) ambient.setX(1.);
|
||||
displayMessage(QString("Light color=(%1 %2 %3).").
|
||||
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::AltModifier))
|
||||
{
|
||||
ambient.setY(ambient.y()+.1);
|
||||
if (ambient.y()>1.) ambient.setY(1.);
|
||||
displayMessage(QString("Light color=(%1 %2 %3).").
|
||||
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::ControlModifier))
|
||||
{
|
||||
ambient.setZ(ambient.z()+.1);
|
||||
if (ambient.z()>1.) ambient.setZ(1.);
|
||||
displayMessage(QString("Light color=(%1 %2 %3).").
|
||||
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_PageDown) && (modifiers==Qt::ShiftModifier))
|
||||
{
|
||||
ambient.setX(ambient.x()-.1);
|
||||
if (ambient.x()<0.) ambient.setX(0.);
|
||||
displayMessage(QString("Light color=(%1 %2 %3).").
|
||||
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_PageDown) && (modifiers==Qt::AltModifier))
|
||||
{
|
||||
ambient.setY(ambient.y()-.1);
|
||||
if (ambient.y()<0.) ambient.setY(0.);
|
||||
displayMessage(QString("Light color=(%1 %2 %3).").
|
||||
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
|
||||
update();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_PageDown) && (modifiers==Qt::ControlModifier))
|
||||
{
|
||||
ambient.setZ(ambient.z()-.1);
|
||||
if (ambient.z()<0.) ambient.setZ(0.);
|
||||
displayMessage(QString("Light color=(%1 %2 %3).").
|
||||
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
|
||||
update();
|
||||
}
|
||||
else
|
||||
CGAL::QGLViewer::keyPressEvent(e);
|
||||
// const Qt::KeyboardModifiers modifiers = e->modifiers();
|
||||
Base::keyPressEvent(e);
|
||||
}
|
||||
|
||||
QString Viewer::helpString() const
|
||||
{
|
||||
QString text("<h2>L C C V i e w e r</h2>");
|
||||
text += "Use the mouse to move the camera around the object. ";
|
||||
text += "You can respectively revolve around, zoom and translate with "
|
||||
"the three mouse buttons. ";
|
||||
text += "Left and middle buttons pressed together rotate around the "
|
||||
"camera view direction axis<br><br>";
|
||||
text += "Pressing <b>Alt</b> and one of the function keys "
|
||||
"(<b>F1</b>..<b>F12</b>) defines a camera keyFrame. ";
|
||||
text += "Simply press the function key again to restore it. Several "
|
||||
"keyFrames define a ";
|
||||
text += "camera path. Paths are saved when you quit the application and "
|
||||
"restored at next start.<br><br>";
|
||||
text += "Press <b>F</b> to display the frame rate, <b>A</b> for the "
|
||||
"world axis, ";
|
||||
text += "<b>Alt+Return</b> for full screen mode and <b>Control+S</b> to "
|
||||
"save a snapshot. ";
|
||||
text += "See the <b>Keyboard</b> tab in this window for a complete "
|
||||
"shortcut list.<br><br>";
|
||||
text += "Double clicks automates single click actions: A left button "
|
||||
"double click aligns the closer axis with the camera (if close enough). ";
|
||||
text += "A middle button double click fits the zoom of the camera and "
|
||||
"the right button re-centers the scene.<br><br>";
|
||||
text += "A left button double click while holding right button pressed "
|
||||
"defines the camera <i>Revolve Around Point</i>. ";
|
||||
text += "See the <b>Mouse</b> tab and the documentation web pages for "
|
||||
"details.<br><br>";
|
||||
text += "Press <b>Escape</b> to exit the viewer.";
|
||||
return text;
|
||||
}
|
||||
{ return Base::helpString("LCC Demo"); }
|
||||
|
||||
|
|
|
|||
|
|
@ -23,96 +23,114 @@
|
|||
#define VIEWER_H
|
||||
|
||||
#include "typedefs.h"
|
||||
#include <CGAL/draw_linear_cell_complex.h>
|
||||
|
||||
#include <vector>
|
||||
#include <QMap>
|
||||
#include <CGAL/Qt/qglviewer.h>
|
||||
#include <QKeyEvent>
|
||||
#include <QOpenGLFunctions_2_1>
|
||||
#include <QOpenGLVertexArrayObject>
|
||||
#include <QGLBuffer>
|
||||
#include <QOpenGLShaderProgram>
|
||||
// Functor used by SimpleLCCViewerQt to colorize of not elements.
|
||||
struct MyDrawingFunctorLCC
|
||||
{
|
||||
/// @return true iff the volume containing dh is drawn.
|
||||
template<typename LCC>
|
||||
bool draw_volume(const LCC& alcc,
|
||||
typename LCC::Dart_const_handle dh) const
|
||||
{ return alcc.template info<3>(dh).is_visible(); }
|
||||
/// @return true iff the face containing dh is drawn.
|
||||
template<typename LCC>
|
||||
bool draw_face(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return true; }
|
||||
/// @return true iff the edge containing dh is drawn.
|
||||
template<typename LCC>
|
||||
bool draw_edge(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return true; }
|
||||
/// @return true iff the vertex containing dh is drawn.
|
||||
template<typename LCC>
|
||||
bool draw_vertex(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return true; }
|
||||
|
||||
#define NB_VBO_BUFFERS 8
|
||||
#define NB_VAO_BUFFERS 4
|
||||
/// @return true iff the volume containing dh is drawn in wireframe.
|
||||
template<typename LCC>
|
||||
bool volume_wireframe(const LCC& alcc,
|
||||
typename LCC::Dart_const_handle dh) const
|
||||
{ return !(alcc.template info<3>(dh).is_filled()); }
|
||||
/// @return true iff the face containing dh is drawn in wireframe.
|
||||
template<typename LCC>
|
||||
bool face_wireframe(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return false; }
|
||||
|
||||
class Viewer : public CGAL::QGLViewer
|
||||
/// @return true iff the volume containing dh is colored.
|
||||
template<typename LCC>
|
||||
bool colored_volume(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return true; }
|
||||
/// @return true iff the face containing dh is colored.
|
||||
/// if we have also colored_volume(alcc, dh), the volume color is
|
||||
/// ignored and only the face color is considered.
|
||||
template<typename LCC>
|
||||
bool colored_face(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return false; }
|
||||
/// @return true iff the edge containing dh is colored.
|
||||
template<typename LCC>
|
||||
bool colored_edge(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return false; }
|
||||
/// @return true iff the vertex containing dh is colored.
|
||||
template<typename LCC>
|
||||
bool colored_vertex(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return false; }
|
||||
|
||||
/// @return the color of the volume containing dh
|
||||
/// used only if colored_volume(alcc, dh) and !colored_face(alcc, dh)
|
||||
template<typename LCC>
|
||||
CGAL::Color volume_color(const LCC& alcc,
|
||||
typename LCC::Dart_const_handle dh) const
|
||||
{ return alcc.template info<3>(dh).color(); }
|
||||
/// @return the color of the face containing dh
|
||||
/// used only if colored_face(alcc, dh)
|
||||
template<typename LCC>
|
||||
CGAL::Color face_color(const LCC& alcc,
|
||||
typename LCC::Dart_const_handle dh) const
|
||||
{
|
||||
CGAL::Random random((unsigned int)(alcc.darts().index(dh)));
|
||||
return get_random_color(random);
|
||||
}
|
||||
/// @return the color of the edge containing dh
|
||||
/// used only if colored_edge(alcc, dh)
|
||||
template<typename LCC>
|
||||
CGAL::Color edge_color(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return CGAL::Color(0, 0, 0); }
|
||||
/// @return the color of the vertex containing dh
|
||||
/// used only if colored_vertex(alcc, dh)
|
||||
template<typename LCC>
|
||||
CGAL::Color vertex_color(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return CGAL::Color(0, 0, 0); }
|
||||
};
|
||||
|
||||
|
||||
class Viewer : public CGAL::SimpleLCCViewerQt<LCC, MyDrawingFunctorLCC>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
typedef LCC::Dart_handle Dart_handle;
|
||||
typedef LCC::Dart_const_handle Dart_const_handle;
|
||||
typedef CGAL::SimpleLCCViewerQt<LCC, MyDrawingFunctorLCC> Base;
|
||||
|
||||
public:
|
||||
Viewer(QWidget* parent);
|
||||
|
||||
~Viewer();
|
||||
|
||||
void setScene(Scene* scene_)
|
||||
{ scene = scene_; }
|
||||
|
||||
public:
|
||||
void draw();
|
||||
|
||||
virtual void init();
|
||||
|
||||
void setScene(Scene* scene_, bool doredraw=true);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
|
||||
virtual QString helpString() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
void sceneChanged();
|
||||
|
||||
private:
|
||||
void initialize_buffers();
|
||||
void attrib_buffers(CGAL::QGLViewer*);
|
||||
void compile_shaders();
|
||||
|
||||
void compute_elements();
|
||||
void compute_face(Dart_handle dh, LCC::size_type markface);
|
||||
void compute_edge(Dart_handle dh, LCC::size_type markedge);
|
||||
void compute_vertex(Dart_handle dh, LCC::size_type markvertex, bool& empty);
|
||||
|
||||
private:
|
||||
Scene* scene;
|
||||
|
||||
bool wireframe;
|
||||
bool flatShading;
|
||||
bool edges;
|
||||
bool vertices;
|
||||
bool inverse_normal;
|
||||
|
||||
double size_points;
|
||||
double size_edges;
|
||||
|
||||
QVector4D ambient;
|
||||
|
||||
bool m_previous_scene_empty;
|
||||
bool are_buffers_initialized;
|
||||
|
||||
//Shaders elements
|
||||
int vertexLocation[3];
|
||||
int normalsLocation;
|
||||
int mvpLocation[2];
|
||||
int mvLocation;
|
||||
int colorLocation;
|
||||
int colorsLocation;
|
||||
int lightLocation[5];
|
||||
|
||||
std::vector<float> pos_points;
|
||||
std::vector<float> pos_lines;
|
||||
std::vector<float> pos_facets;
|
||||
std::vector<float> smooth_normals;
|
||||
std::vector<float> flat_normals;
|
||||
std::vector<float> colors;
|
||||
|
||||
QGLBuffer buffers[NB_VBO_BUFFERS];
|
||||
QOpenGLVertexArrayObject vao[NB_VAO_BUFFERS];
|
||||
QOpenGLShaderProgram rendering_program;
|
||||
QOpenGLShaderProgram rendering_program_p_l;
|
||||
|
||||
CGAL::Bbox_3 bb;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -31,15 +31,96 @@ namespace CGAL
|
|||
{
|
||||
|
||||
// Default color functor; user can change it to have its own face color
|
||||
struct DefaultColorFunctorLCC
|
||||
struct DefaultDrawingFunctorLCC
|
||||
{
|
||||
/// @return true iff the volume containing dh is drawn.
|
||||
template<typename LCC>
|
||||
static CGAL::Color run(const LCC& alcc,
|
||||
typename LCC::Dart_const_handle dh)
|
||||
{
|
||||
if (dh==alcc.null_handle) // use to get the mono color
|
||||
return CGAL::Color(100, 125, 200); // R G B between 0-255
|
||||
bool draw_volume(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return true; }
|
||||
/// @return true iff the face containing dh is drawn.
|
||||
template<typename LCC>
|
||||
bool draw_face(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return true; }
|
||||
/// @return true iff the edge containing dh is drawn.
|
||||
template<typename LCC>
|
||||
bool draw_edge(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return true; }
|
||||
/// @return true iff the vertex containing dh is drawn.
|
||||
template<typename LCC>
|
||||
bool draw_vertex(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return true; }
|
||||
|
||||
/// @return true iff the volume containing dh is drawn in wireframe.
|
||||
template<typename LCC>
|
||||
bool volume_wireframe(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return false; }
|
||||
/// @return true iff the face containing dh is drawn in wireframe.
|
||||
template<typename LCC>
|
||||
bool face_wireframe(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return false; }
|
||||
|
||||
/// @return true iff the volume containing dh is colored.
|
||||
template<typename LCC>
|
||||
bool colored_volume(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return true; }
|
||||
/// @return true iff the face containing dh is colored.
|
||||
/// if we have also colored_volume(alcc, dh), the volume color is
|
||||
/// ignored and only the face color is considered.
|
||||
template<typename LCC>
|
||||
bool colored_face(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return false; }
|
||||
/// @return true iff the edge containing dh is colored.
|
||||
template<typename LCC>
|
||||
bool colored_edge(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return false; }
|
||||
/// @return true iff the vertex containing dh is colored.
|
||||
template<typename LCC>
|
||||
bool colored_vertex(const LCC&,
|
||||
typename LCC::Dart_const_handle) const
|
||||
{ return false; }
|
||||
|
||||
/// @return the color of the volume containing dh
|
||||
/// used only if colored_volume(alcc, dh) and !colored_face(alcc, dh)
|
||||
template<typename LCC>
|
||||
CGAL::Color volume_color(const LCC& alcc,
|
||||
typename LCC::Dart_const_handle dh) const
|
||||
{
|
||||
CGAL::Random random((unsigned int)(alcc.darts().index(dh)));
|
||||
return get_random_color(random);
|
||||
}
|
||||
/// @return the color of the face containing dh
|
||||
/// used only if colored_face(alcc, dh)
|
||||
template<typename LCC>
|
||||
CGAL::Color face_color(const LCC& alcc,
|
||||
typename LCC::Dart_const_handle dh) const
|
||||
{
|
||||
CGAL::Random random((unsigned int)(alcc.darts().index(dh)));
|
||||
return get_random_color(random);
|
||||
}
|
||||
/// @return the color of the edge containing dh
|
||||
/// used only if colored_edge(alcc, dh)
|
||||
template<typename LCC>
|
||||
CGAL::Color edge_color(const LCC& alcc,
|
||||
typename LCC::Dart_const_handle dh) const
|
||||
{
|
||||
CGAL::Random random((unsigned int)(alcc.darts().index(dh)));
|
||||
return get_random_color(random);
|
||||
}
|
||||
/// @return the color of the vertex containing dh
|
||||
/// used only if colored_vertex(alcc, dh)
|
||||
template<typename LCC>
|
||||
CGAL::Color vertex_color(const LCC& alcc,
|
||||
typename LCC::Dart_const_handle dh) const
|
||||
{
|
||||
CGAL::Random random((unsigned int)(alcc.darts().index(dh)));
|
||||
return get_random_color(random);
|
||||
}
|
||||
|
|
@ -73,7 +154,7 @@ struct LCC_geom_utils<LCC, Kernel, 2>
|
|||
};
|
||||
|
||||
// Viewer class for LCC
|
||||
template<class LCC, class ColorFunctor>
|
||||
template<class LCC, class DrawingFunctorLCC>
|
||||
class SimpleLCCViewerQt : public Basic_viewer_qt
|
||||
{
|
||||
typedef Basic_viewer_qt Base;
|
||||
|
|
@ -89,42 +170,68 @@ public:
|
|||
/// @param anofaces if true, do not draw faces (faces are not computed; this can be
|
||||
/// usefull for very big object where this time could be long)
|
||||
SimpleLCCViewerQt(QWidget* parent,
|
||||
const LCC& alcc,
|
||||
const LCC* alcc=NULL,
|
||||
const char* title="Basic LCC Viewer",
|
||||
bool anofaces=false,
|
||||
const ColorFunctor& fcolor=ColorFunctor()) :
|
||||
const DrawingFunctorLCC& drawing_functor=DrawingFunctorLCC()) :
|
||||
// First draw: vertices; edges, faces; multi-color; inverse normal
|
||||
Base(parent, title, true, true, true, false, true),
|
||||
lcc(alcc),
|
||||
m_nofaces(anofaces),
|
||||
m_fcolor(fcolor)
|
||||
m_random_face_color(false),
|
||||
m_drawing_functor(drawing_functor)
|
||||
{
|
||||
compute_elements();
|
||||
}
|
||||
|
||||
protected:
|
||||
void compute_face(Dart_const_handle dh)
|
||||
void set_lcc(const LCC* alcc, bool doredraw=true)
|
||||
{
|
||||
lcc=alcc;
|
||||
compute_elements();
|
||||
if (doredraw) { redraw(); }
|
||||
}
|
||||
|
||||
void compute_face(Dart_const_handle dh, Dart_const_handle voldh)
|
||||
{
|
||||
if (m_nofaces || !m_drawing_functor.draw_face(*lcc, dh)) return;
|
||||
|
||||
// We fill only closed faces.
|
||||
Dart_const_handle cur=dh;
|
||||
Dart_const_handle min=dh;
|
||||
do
|
||||
{
|
||||
if (!lcc.is_next_exist(cur)) return; // open face=>not filled
|
||||
if (!lcc->is_next_exist(cur)) return; // open face=>not filled
|
||||
if (cur<min) min=cur;
|
||||
cur=lcc.next(cur);
|
||||
cur=lcc->next(cur);
|
||||
}
|
||||
while(cur!=dh);
|
||||
|
||||
CGAL::Color c=m_fcolor.run(lcc, dh);
|
||||
face_begin(c);
|
||||
|
||||
if (m_random_face_color)
|
||||
{
|
||||
CGAL::Random random((unsigned int)(lcc->darts().index(dh)));
|
||||
CGAL::Color c=get_random_color(random);
|
||||
face_begin(c);
|
||||
}
|
||||
else if (m_drawing_functor.colored_face(*lcc, dh))
|
||||
{
|
||||
CGAL::Color c=m_drawing_functor.face_color(*lcc, dh);
|
||||
face_begin(c);
|
||||
}
|
||||
else if (m_drawing_functor.colored_volume(*lcc, voldh))
|
||||
{
|
||||
CGAL::Color c=m_drawing_functor.volume_color(*lcc, voldh);
|
||||
face_begin(c);
|
||||
}
|
||||
else
|
||||
{ face_begin(); }
|
||||
|
||||
cur=dh;
|
||||
do
|
||||
{
|
||||
add_point_in_face(lcc.point(cur), LCC_geom_utils<LCC, Local_kernel>::
|
||||
get_vertex_normal(lcc, cur));
|
||||
cur=lcc.next(cur);
|
||||
add_point_in_face(lcc->point(cur), LCC_geom_utils<LCC, Local_kernel>::
|
||||
get_vertex_normal(*lcc, cur));
|
||||
cur=lcc->next(cur);
|
||||
}
|
||||
while(cur!=dh);
|
||||
|
||||
|
|
@ -133,77 +240,143 @@ protected:
|
|||
|
||||
void compute_edge(Dart_const_handle dh)
|
||||
{
|
||||
Point p1 = lcc.point(dh);
|
||||
Dart_const_handle d2 = lcc.other_extremity(dh);
|
||||
if (!m_drawing_functor.draw_edge(*lcc, dh)) return;
|
||||
|
||||
Point p1 = lcc->point(dh);
|
||||
Dart_const_handle d2 = lcc->other_extremity(dh);
|
||||
if (d2!=NULL)
|
||||
{ add_segment(p1, lcc.point(d2)); }
|
||||
{
|
||||
if (m_drawing_functor.colored_edge(*lcc, dh))
|
||||
{ add_segment(p1, lcc->point(d2), m_drawing_functor.edge_color(*lcc, dh)); }
|
||||
else
|
||||
{ add_segment(p1, lcc->point(d2)); }
|
||||
}
|
||||
}
|
||||
|
||||
void compute_vertex(Dart_const_handle dh)
|
||||
{ add_point(lcc.point(dh)); }
|
||||
{
|
||||
if (!m_drawing_functor.draw_vertex(*lcc, dh)) return;
|
||||
|
||||
if (m_drawing_functor.colored_vertex(*lcc, dh))
|
||||
{ add_point(lcc->point(dh), m_drawing_functor.vertex_color(*lcc, dh)); }
|
||||
else
|
||||
{ add_point(lcc->point(dh)); }
|
||||
}
|
||||
|
||||
void compute_elements()
|
||||
{
|
||||
clear();
|
||||
if (lcc==NULL) return;
|
||||
|
||||
typename LCC::size_type markvolumes = lcc->get_new_mark();
|
||||
typename LCC::size_type markfaces = lcc->get_new_mark();
|
||||
typename LCC::size_type markedges = lcc->get_new_mark();
|
||||
typename LCC::size_type markvertices = lcc->get_new_mark();
|
||||
|
||||
typename LCC::size_type markfaces = lcc.get_new_mark();
|
||||
typename LCC::size_type markedges = lcc.get_new_mark();
|
||||
typename LCC::size_type markvertices = lcc.get_new_mark();
|
||||
|
||||
for (typename LCC::Dart_range::const_iterator it=lcc.darts().begin(),
|
||||
itend=lcc.darts().end(); it!=itend; ++it )
|
||||
for (typename LCC::Dart_range::const_iterator it=lcc->darts().begin(),
|
||||
itend=lcc->darts().end(); it!=itend; ++it )
|
||||
{
|
||||
if ( !m_nofaces && !lcc.is_marked(it, markfaces) )
|
||||
if (!lcc->is_marked(it, markvolumes) &&
|
||||
m_drawing_functor.draw_volume(*lcc, it))
|
||||
{
|
||||
compute_face(it);
|
||||
CGAL::mark_cell<LCC, 2>(lcc, it, markfaces);
|
||||
}
|
||||
|
||||
if ( !lcc.is_marked(it, markedges) )
|
||||
{
|
||||
compute_edge(it);
|
||||
CGAL::mark_cell<LCC, 1>(lcc, it, markedges);
|
||||
}
|
||||
|
||||
if ( !lcc.is_marked(it, markvertices) )
|
||||
{
|
||||
compute_vertex(it);
|
||||
CGAL::mark_cell<LCC, 0>(lcc, it, markvertices);
|
||||
for (typename LCC::template Dart_of_cell_basic_range<3>::
|
||||
const_iterator itv=lcc->template darts_of_cell_basic<3>(it, markvolumes).begin(),
|
||||
itvend=lcc->template darts_of_cell_basic<3>(it, markvolumes).end();
|
||||
itv!=itvend; ++itv)
|
||||
{
|
||||
lcc->mark(itv, markvolumes); // To be sure that all darts of the basic iterator will be marked
|
||||
if (!lcc->is_marked(itv, markfaces) &&
|
||||
m_drawing_functor.draw_face(*lcc, itv))
|
||||
{
|
||||
if (!m_drawing_functor.volume_wireframe(*lcc, itv) &&
|
||||
!m_drawing_functor.face_wireframe(*lcc, itv))
|
||||
{ compute_face(itv, it); }
|
||||
for (typename LCC::template Dart_of_cell_basic_range<2>::
|
||||
const_iterator itf=lcc->template darts_of_cell_basic<2>(itv, markfaces).begin(),
|
||||
itfend=lcc->template darts_of_cell_basic<2>(itv, markfaces).end();
|
||||
itf!=itfend; ++itf)
|
||||
{
|
||||
if (!m_drawing_functor.volume_wireframe(*lcc, itv) &&
|
||||
!m_drawing_functor.face_wireframe(*lcc, itv))
|
||||
{ lcc->mark(itf, markfaces); } // To be sure that all darts of the basic iterator will be marked
|
||||
if ( !lcc->is_marked(itf, markedges) &&
|
||||
m_drawing_functor.draw_edge(*lcc, itf))
|
||||
{
|
||||
compute_edge(itf);
|
||||
for (typename LCC::template Dart_of_cell_basic_range<1>::
|
||||
const_iterator ite=lcc->template darts_of_cell_basic<1>(itf, markedges).begin(),
|
||||
iteend=lcc->template darts_of_cell_basic<1>(itf, markedges).end();
|
||||
ite!=iteend; ++ite)
|
||||
{
|
||||
lcc->mark(ite, markedges); // To be sure that all darts of the basic iterator will be marked
|
||||
if ( !lcc->is_marked(ite, markvertices) &&
|
||||
m_drawing_functor.draw_vertex(*lcc, ite))
|
||||
{
|
||||
compute_vertex(ite);
|
||||
CGAL::mark_cell<LCC, 0>(*lcc, ite, markvertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lcc.free_mark(markfaces);
|
||||
lcc.free_mark(markedges);
|
||||
lcc.free_mark(markvertices);
|
||||
}
|
||||
for (typename LCC::Dart_range::const_iterator it=lcc->darts().begin(),
|
||||
itend=lcc->darts().end(); it!=itend; ++it )
|
||||
{
|
||||
lcc->unmark(it, markvertices);
|
||||
lcc->unmark(it, markedges);
|
||||
lcc->unmark(it, markfaces);
|
||||
lcc->unmark(it, markvolumes);
|
||||
|
||||
}
|
||||
|
||||
lcc->free_mark(markvolumes);
|
||||
lcc->free_mark(markfaces);
|
||||
lcc->free_mark(markedges);
|
||||
lcc->free_mark(markvertices);
|
||||
}
|
||||
|
||||
virtual void init()
|
||||
{
|
||||
Base::init();
|
||||
setKeyDescription(::Qt::Key_C, "Toggles random face colors");
|
||||
}
|
||||
|
||||
virtual void keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
// Test key pressed:
|
||||
// const ::Qt::KeyboardModifiers modifiers = e->modifiers();
|
||||
// if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... }
|
||||
const ::Qt::KeyboardModifiers modifiers = e->modifiers();
|
||||
if ((e->key()==::Qt::Key_C) && (modifiers==::Qt::NoButton))
|
||||
{
|
||||
m_random_face_color=!m_random_face_color;
|
||||
displayMessage(QString("Random face color=%1.").arg(m_random_face_color?"true":"false"));
|
||||
compute_elements();
|
||||
redraw();
|
||||
}
|
||||
else
|
||||
{ Base::keyPressEvent(e); } // Call the base method to process others/classicals key
|
||||
|
||||
// Call: * compute_elements() if the model changed, followed by
|
||||
// * redraw() if some viewing parameters changed that implies some
|
||||
// modifications of the buffers
|
||||
// (eg. type of normal, color/mono)
|
||||
// * update() just to update the drawing
|
||||
|
||||
// Call the base method to process others/classicals key
|
||||
Base::keyPressEvent(e);
|
||||
}
|
||||
|
||||
protected:
|
||||
const LCC& lcc;
|
||||
const LCC* lcc;
|
||||
bool m_nofaces;
|
||||
const ColorFunctor& m_fcolor;
|
||||
bool m_random_face_color;
|
||||
const DrawingFunctorLCC& m_drawing_functor;
|
||||
};
|
||||
|
||||
template<class LCC, class ColorFunctor>
|
||||
template<class LCC, class DrawingFunctorLCC>
|
||||
void draw(const LCC& alcc,
|
||||
const char* title,
|
||||
bool nofill,
|
||||
const ColorFunctor& fcolor)
|
||||
const DrawingFunctorLCC& drawing_functor)
|
||||
{
|
||||
#if defined(CGAL_TEST_SUITE)
|
||||
bool cgal_test_suite=true;
|
||||
|
|
@ -216,11 +389,11 @@ void draw(const LCC& alcc,
|
|||
int argc=1;
|
||||
const char* argv[2]={"lccviewer","\0"};
|
||||
QApplication app(argc,const_cast<char**>(argv));
|
||||
SimpleLCCViewerQt<LCC, ColorFunctor> mainwindow(app.activeWindow(),
|
||||
alcc,
|
||||
title,
|
||||
nofill,
|
||||
fcolor);
|
||||
SimpleLCCViewerQt<LCC, DrawingFunctorLCC> mainwindow(app.activeWindow(),
|
||||
&alcc,
|
||||
title,
|
||||
nofill,
|
||||
drawing_functor);
|
||||
mainwindow.show();
|
||||
app.exec();
|
||||
}
|
||||
|
|
@ -229,8 +402,8 @@ void draw(const LCC& alcc,
|
|||
template<class LCC>
|
||||
void draw(const LCC& alcc, const char* title, bool nofill)
|
||||
{
|
||||
DefaultColorFunctorLCC c;
|
||||
draw(alcc, title, nofill, c);
|
||||
DefaultDrawingFunctorLCC f;
|
||||
draw(alcc, title, nofill, f);
|
||||
}
|
||||
|
||||
template<class LCC>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ int main(int argc, char** argv)
|
|||
std::cerr << "Assignment f2=f...\n";
|
||||
f2 = f; // check the assignment
|
||||
std::cerr << "Auto-assignment f=f...\n";
|
||||
f2 = f2; // check the auto-assignment
|
||||
f2 = (Map&)f2; // check the auto-assignment
|
||||
std::cerr << "Copy-construction...\n";
|
||||
Map f3(f); // check the copy constructor
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ int main()
|
|||
|
||||
assert(mod_x == CGAL::modular_image(int_x));
|
||||
int_x -= int_x; int_x = CGAL::mod(int_x, prime);
|
||||
mod_x -= mod_x;
|
||||
mod_x -= (CGAL::Residue&)mod_x;
|
||||
}
|
||||
{
|
||||
CGAL::Residue::set_current_prime(67111043);
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ bool multiplication_test()
|
|||
g = d * e;
|
||||
h = d * f;
|
||||
i = a * e;
|
||||
j = j;
|
||||
j = (IA_nt&)j;
|
||||
|
||||
// When CGAL_IA_DEBUG is defined, it'll test the current rounding mode for
|
||||
// these operations.
|
||||
|
|
|
|||
|
|
@ -119,34 +119,47 @@ clip_to_bbox(const Plane_3& plane,
|
|||
int current_id = face_indices[4*i + k];
|
||||
int next_id = face_indices[4*i + (k+1)%4];
|
||||
|
||||
if ( orientations[ current_id ] != ON_POSITIVE_SIDE )
|
||||
switch(orientations[ current_id ])
|
||||
{
|
||||
all_out=false;
|
||||
// point on or on the negative side
|
||||
output_faces[i].push_back( current_id );
|
||||
in_point_ids.insert( output_faces[i].back() );
|
||||
// check for intersection of the edge
|
||||
if (orientations[ current_id ] == ON_NEGATIVE_SIDE &&
|
||||
orientations[ next_id ] == ON_POSITIVE_SIDE)
|
||||
case ON_NEGATIVE_SIDE:
|
||||
{
|
||||
output_faces[i].push_back(
|
||||
inter_pt_index<Geom_traits>(current_id, next_id, plane, corners, id_map) );
|
||||
all_out=false;
|
||||
// point on or on the negative side
|
||||
output_faces[i].push_back( current_id );
|
||||
in_point_ids.insert( output_faces[i].back() );
|
||||
// check for intersection of the edge
|
||||
if (orientations[ next_id ] == ON_POSITIVE_SIDE)
|
||||
{
|
||||
output_faces[i].push_back(
|
||||
inter_pt_index<Geom_traits>(current_id, next_id, plane, corners, id_map) );
|
||||
in_point_ids.insert( output_faces[i].back() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
all_in = false;
|
||||
// check for intersection of the edge
|
||||
if ( orientations[ next_id ] == ON_NEGATIVE_SIDE )
|
||||
case ON_POSITIVE_SIDE:
|
||||
{
|
||||
output_faces[i].push_back(
|
||||
inter_pt_index<Geom_traits>(current_id, next_id, plane, corners, id_map) );
|
||||
all_in = false;
|
||||
// check for intersection of the edge
|
||||
if ( orientations[ next_id ] == ON_NEGATIVE_SIDE )
|
||||
{
|
||||
output_faces[i].push_back(
|
||||
inter_pt_index<Geom_traits>(current_id, next_id, plane, corners, id_map) );
|
||||
in_point_ids.insert( output_faces[i].back() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_ORIENTED_BOUNDARY:
|
||||
{
|
||||
output_faces[i].push_back( current_id );
|
||||
in_point_ids.insert( output_faces[i].back() );
|
||||
}
|
||||
}
|
||||
}
|
||||
CGAL_assertion( output_faces[i].empty() || output_faces[i].size() >= 3 );
|
||||
if (output_faces[i].size() < 3){
|
||||
CGAL_assertion(output_faces[i].empty() ||
|
||||
(output_faces[i].front()<8 && output_faces[i].back()<8) );
|
||||
output_faces[i].clear(); // edge of the bbox included in the plane
|
||||
}
|
||||
}
|
||||
|
||||
// the intersection is the full bbox
|
||||
|
|
|
|||
|
|
@ -103,8 +103,7 @@ class Face_graph_output_builder
|
|||
// Internal typedefs
|
||||
typedef std::size_t Node_id;
|
||||
typedef std::pair<Node_id,Node_id> Node_id_pair;
|
||||
typedef boost::unordered_map<edge_descriptor,
|
||||
Node_id_pair > Intersection_edge_map;
|
||||
typedef boost::unordered_set<edge_descriptor> Intersection_edge_map;
|
||||
// to maintain a halfedge on each polyline per TriangleMesh + pair<bool,size_t>
|
||||
// with first = "is the key (pair<Node_id,Node_id>) was reversed?" and
|
||||
// second is the number of edges -1 in the polyline
|
||||
|
|
@ -127,6 +126,9 @@ class Face_graph_output_builder
|
|||
const VpmOutTuple& output_vpms;
|
||||
EdgeMarkMapTuple& out_edge_mark_maps;
|
||||
UserVisitor& user_visitor;
|
||||
// mapping vertex to node id
|
||||
Node_id_map vertex_to_node_id1, vertex_to_node_id2;
|
||||
|
||||
// output meshes
|
||||
const cpp11::array<boost::optional<TriangleMesh*>, 4>& requested_output;
|
||||
// input meshes closed ?
|
||||
|
|
@ -310,9 +312,8 @@ class Face_graph_output_builder
|
|||
{
|
||||
std::vector<edge_descriptor> edges;
|
||||
edges.reserve(edge_map.size());
|
||||
typedef std::pair<const edge_descriptor, Node_id_pair> Pair;
|
||||
BOOST_FOREACH(const Pair& p, edge_map)
|
||||
edges.push_back(p.first);
|
||||
BOOST_FOREACH(edge_descriptor ed, edge_map)
|
||||
edges.push_back(ed);
|
||||
|
||||
CGAL_assertion(tuple_id < 4 && tuple_id >= 0);
|
||||
switch (tuple_id)
|
||||
|
|
@ -427,8 +428,7 @@ public:
|
|||
//register an intersection halfedge
|
||||
// It is important here not to use operator[] since a two edges might be
|
||||
// equals while the indices are reversed
|
||||
mesh_to_intersection_edges[&tm].
|
||||
insert(std::make_pair(edge(hedge, tm), indices));
|
||||
mesh_to_intersection_edges[&tm].insert(edge(hedge, tm));
|
||||
|
||||
if (indices.first>indices.second)
|
||||
{
|
||||
|
|
@ -445,6 +445,17 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void set_vertex_id(vertex_descriptor v, Node_id node_id, const TriangleMesh& tm)
|
||||
{
|
||||
if (&tm == &tm1)
|
||||
vertex_to_node_id1.insert( std::make_pair(v, node_id) );
|
||||
else
|
||||
{
|
||||
CGAL_assertion(&tm == &tm2);
|
||||
vertex_to_node_id2.insert( std::make_pair(v, node_id) );
|
||||
}
|
||||
}
|
||||
|
||||
template <class Nodes_vector, class Mesh_to_map_node>
|
||||
void operator()(
|
||||
const Nodes_vector& nodes,
|
||||
|
|
@ -452,30 +463,11 @@ public:
|
|||
const boost::dynamic_bitset<>& is_node_of_degree_one,
|
||||
const Mesh_to_map_node&)
|
||||
{
|
||||
// first build an unordered_map mapping a vertex to its node id
|
||||
CGAL_assertion( vertex_to_node_id1.size() == vertex_to_node_id2.size());
|
||||
CGAL_assertion( vertex_to_node_id1.size() == nodes.size());
|
||||
|
||||
Intersection_edge_map& intersection_edges1 = mesh_to_intersection_edges[&tm1];
|
||||
Node_id_map vertex_to_node_id1;
|
||||
|
||||
for (typename Intersection_edge_map::iterator
|
||||
it=intersection_edges1.begin(),
|
||||
it_end=intersection_edges1.end(); it!=it_end; ++it)
|
||||
{
|
||||
vertex_to_node_id1[source(it->first,tm1)]=it->second.first;
|
||||
vertex_to_node_id1[target(it->first,tm1)]=it->second.second;
|
||||
}
|
||||
|
||||
Intersection_edge_map& intersection_edges2 = mesh_to_intersection_edges[&tm2];
|
||||
Node_id_map vertex_to_node_id2;
|
||||
|
||||
for (typename Intersection_edge_map::iterator
|
||||
it=intersection_edges2.begin(),
|
||||
it_end=intersection_edges2.end(); it!=it_end; ++it)
|
||||
{
|
||||
vertex_to_node_id2[source(it->first,tm2)]=it->second.first;
|
||||
vertex_to_node_id2[target(it->first,tm2)]=it->second.second;
|
||||
}
|
||||
|
||||
CGAL_assertion(intersection_edges1.size()==intersection_edges2.size());
|
||||
|
||||
// this will initialize face indices if the face index map is writable.
|
||||
helpers::init_face_indices(tm1, fids1);
|
||||
|
|
@ -504,11 +496,6 @@ public:
|
|||
halfedge_descriptor h2 = epp_it->second.first[&tm2];
|
||||
halfedge_descriptor h2_opp = opposite(h2, tm2);
|
||||
|
||||
if (is_border_edge(h1,tm1) || is_border_edge(h2,tm2)){
|
||||
++epp_it;
|
||||
continue;
|
||||
}
|
||||
|
||||
//vertices from tm1
|
||||
vertex_descriptor p1 = target(next(h1_opp, tm1), tm1);
|
||||
vertex_descriptor p2 = target(next(h1, tm1), tm1);
|
||||
|
|
@ -521,41 +508,53 @@ public:
|
|||
Node_id index_q2 = get_node_id(q2, vertex_to_node_id2);
|
||||
|
||||
// set boolean for the position of p1 wrt to q1 and q2
|
||||
bool p1_eq_q1=false, p1_eq_q2=false;
|
||||
bool p1_eq_q1=is_border(h1_opp, tm1), p1_eq_q2=p1_eq_q1;
|
||||
if (!is_border(h1_opp, tm1) && index_p1!=NID)
|
||||
{
|
||||
if (!is_border(h2_opp, tm2))
|
||||
{
|
||||
p1_eq_q1 = index_p1 == index_q1;
|
||||
if (p1_eq_q1)
|
||||
{
|
||||
//mark coplanar facets if any
|
||||
tm1_coplanar_faces.set(get(fids1, face(h1_opp, tm1)));
|
||||
tm2_coplanar_faces.set(get(fids2, face(h2_opp, tm2)));
|
||||
}
|
||||
}
|
||||
if (!is_border(h2, tm2))
|
||||
{
|
||||
p1_eq_q2 = index_p1 == index_q2;
|
||||
if (p1_eq_q2)
|
||||
{
|
||||
//mark coplanar facets if any
|
||||
tm1_coplanar_faces.set(get(fids1, face(h1_opp, tm1)));
|
||||
tm2_coplanar_faces.set(get(fids2, face(h2, tm2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set boolean for the position of p2 wrt to q1 and q2
|
||||
bool p2_eq_q1=false, p2_eq_q2=false;
|
||||
bool p2_eq_q1=is_border(h1, tm1), p2_eq_q2=p2_eq_q1;
|
||||
if (!is_border(h1, tm1) && index_p2!=NID)
|
||||
{
|
||||
if (!is_border(h2_opp, tm2))
|
||||
{
|
||||
p2_eq_q1 = index_p2 == index_q1;
|
||||
if (p2_eq_q1){
|
||||
//mark coplanar facets if any
|
||||
tm1_coplanar_faces.set(get(fids1, face(h1, tm1)));
|
||||
tm2_coplanar_faces.set(get(fids2, face(h2_opp, tm2)));
|
||||
}
|
||||
}
|
||||
if (!is_border(h2, tm2))
|
||||
{
|
||||
p2_eq_q2 = index_p2 == index_q2;
|
||||
}
|
||||
|
||||
//mark coplanar facets if any
|
||||
if (p1_eq_q1){
|
||||
tm1_coplanar_faces.set(get(fids1, face(h1_opp, tm1)));
|
||||
tm2_coplanar_faces.set(get(fids2, face(h2_opp, tm2)));
|
||||
}
|
||||
if (p1_eq_q2){
|
||||
tm1_coplanar_faces.set(get(fids1, face(h1_opp, tm1)));
|
||||
tm2_coplanar_faces.set(get(fids2, face(h2, tm2)));
|
||||
}
|
||||
if (p2_eq_q1){
|
||||
tm1_coplanar_faces.set(get(fids1, face(h1, tm1)));
|
||||
tm2_coplanar_faces.set(get(fids2, face(h2_opp, tm2)));
|
||||
}
|
||||
if (p2_eq_q2){
|
||||
tm1_coplanar_faces.set(get(fids1, face(h1, tm1)));
|
||||
tm2_coplanar_faces.set(get(fids2, face(h2, tm2)));
|
||||
if (p2_eq_q2){
|
||||
//mark coplanar facets if any
|
||||
tm1_coplanar_faces.set(get(fids1, face(h1, tm1)));
|
||||
tm2_coplanar_faces.set(get(fids2, face(h2, tm2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( (p1_eq_q1 || p1_eq_q2) && (p2_eq_q1 || p2_eq_q2) )
|
||||
|
|
@ -565,6 +564,48 @@ public:
|
|||
an_edge_per_polyline.erase(it_to_rm);
|
||||
inter_edges_to_remove1.insert(edge(h1,tm1));
|
||||
inter_edges_to_remove2.insert(edge(h2,tm2));
|
||||
|
||||
// on the border, we can have a degree 2 node so prev/next
|
||||
// halfedge should be also considered for removal
|
||||
// (as the coplanar edge will not be reported in an_edge_per_polyline
|
||||
// and thus not removed from intersection_edges[12])
|
||||
if ( !is_border(h1, tm1) )
|
||||
{
|
||||
h1 = opposite(h1, tm1);
|
||||
h2 = opposite(h2, tm2);
|
||||
}
|
||||
if ( is_border(h1, tm1) )
|
||||
{
|
||||
if ( opposite(next(h1, tm1), tm1) == prev(opposite(h1, tm1), tm1) )
|
||||
{
|
||||
inter_edges_to_remove1.insert(edge(next(h1, tm1),tm1));
|
||||
inter_edges_to_remove1.insert(edge(next(h2, tm2),tm2));
|
||||
}
|
||||
if ( opposite(prev(h1, tm1), tm1) == next(opposite(h1, tm1), tm1) )
|
||||
{
|
||||
inter_edges_to_remove1.insert(edge(prev(h1, tm1), tm1));
|
||||
inter_edges_to_remove1.insert(edge(prev(h2, tm2), tm2));
|
||||
}
|
||||
}
|
||||
// same but for h2
|
||||
if ( !is_border(h2, tm2) )
|
||||
{
|
||||
h1 = opposite(h1, tm1);
|
||||
h2 = opposite(h2, tm2);
|
||||
}
|
||||
if ( is_border(h2, tm2) )
|
||||
{
|
||||
if ( opposite(next(h2, tm2), tm2) == prev(opposite(h2, tm2), tm2) )
|
||||
{
|
||||
inter_edges_to_remove1.insert(edge(next(h1, tm1),tm1));
|
||||
inter_edges_to_remove1.insert(edge(next(h2, tm2),tm2));
|
||||
}
|
||||
if ( opposite(prev(h2, tm2), tm2) == next(opposite(h2, tm2), tm2) )
|
||||
{
|
||||
inter_edges_to_remove1.insert(edge(prev(h1, tm1), tm1));
|
||||
inter_edges_to_remove1.insert(edge(prev(h2, tm2), tm2));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
++epp_it;
|
||||
|
|
@ -601,7 +642,7 @@ public:
|
|||
.face_index_map(fids2));
|
||||
|
||||
std::vector <std::size_t> tm2_patch_sizes(nb_patches_tm2, 0);
|
||||
BOOST_FOREACH(std::size_t i, tm2_patch_ids)
|
||||
BOOST_FOREACH(Node_id i, tm2_patch_ids)
|
||||
if(i!=NID)
|
||||
++tm2_patch_sizes[i];
|
||||
|
||||
|
|
@ -677,11 +718,55 @@ public:
|
|||
impossible_operation.set();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Sort the three triangle faces around their common edge
|
||||
// we assume that the exterior of the volume is indicated by
|
||||
// counterclockwise oriented faces
|
||||
// (corrected by is_tmi_inside_tmi).
|
||||
halfedge_descriptor h = is_border(h1, tm1) ? opposite(h1, tm1) : h1;
|
||||
vertex_descriptor p = target(next(h,tm1),tm1);
|
||||
// when looking from the side of indices.second,
|
||||
// the interior of the first triangle mesh is described
|
||||
// by turning counterclockwise from p1 to p2
|
||||
vertex_descriptor q1=target(next(opposite(h2,tm2),tm2),tm2);
|
||||
vertex_descriptor q2=target(next(h2,tm2),tm2);
|
||||
// when looking from the side of indices.second,
|
||||
// the interior of the second volume is described
|
||||
// by turning from q1 to q2
|
||||
|
||||
//check if the third point of each triangular face is an original point (stay NID)
|
||||
//or a intersection point (in that case we need the index of the corresponding node to
|
||||
//have the exact value of the point)
|
||||
Node_id index_p = get_node_id(p, vertex_to_node_id1);
|
||||
Node_id index_q1 = get_node_id(q1, vertex_to_node_id2);
|
||||
Node_id index_q2 = get_node_id(q2, vertex_to_node_id2);
|
||||
|
||||
std::size_t patch_id_p=tm1_patch_ids[ get(fids1, face(h,tm1)) ];
|
||||
std::size_t patch_id_q1=tm2_patch_ids[ get(fids2, face(opposite(h2,tm2),tm2)) ];
|
||||
std::size_t patch_id_q2=tm2_patch_ids[ get(fids2, face(h2,tm2)) ];
|
||||
|
||||
//indicates that patch status will be updated
|
||||
patch_status_not_set_tm1.reset(patch_id_p);
|
||||
patch_status_not_set_tm2.reset(patch_id_q1);
|
||||
patch_status_not_set_tm2.reset(patch_id_q2);
|
||||
|
||||
bool p_is_between_q1q2 = sorted_around_edge(
|
||||
ids.first, ids.second,
|
||||
index_q1, index_q2, index_p,
|
||||
q1, q2, p,
|
||||
vpm2, vpm1,
|
||||
nodes);
|
||||
|
||||
if (p_is_between_q1q2)
|
||||
is_patch_inside_tm2.set(patch_id_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if ( is_border_edge(h2,tm2) )
|
||||
{
|
||||
CGAL_assertion(!used_to_clip_a_surface);
|
||||
//Ambiguous, we do nothing
|
||||
impossible_operation.set();
|
||||
return;
|
||||
|
|
@ -989,37 +1074,51 @@ public:
|
|||
|
||||
BOOST_FOREACH(face_descriptor f, faces(tm1))
|
||||
{
|
||||
std::size_t patch_id=tm1_patch_ids[ get(fids1, f) ];
|
||||
const std::size_t f_id = get(fids1, f);
|
||||
const std::size_t patch_id = tm1_patch_ids[ f_id ];
|
||||
if ( patch_status_not_set_tm1.test( patch_id ) )
|
||||
{
|
||||
patch_status_not_set_tm1.reset( patch_id );
|
||||
vertex_descriptor v = target(halfedge(f, tm1), tm1);
|
||||
Bounded_side position = inside_tm2( get(vpm1, v));
|
||||
if ( position == in_tm2 )
|
||||
is_patch_inside_tm2.set(patch_id);
|
||||
else
|
||||
if( position == ON_BOUNDARY)
|
||||
halfedge_descriptor h = halfedge(f, tm1);
|
||||
Node_id index_p1 = get_node_id(target(h, tm1), vertex_to_node_id1);
|
||||
if (index_p1 != NID)
|
||||
{
|
||||
h=next(h, tm1);
|
||||
index_p1 = get_node_id(target(h, tm1), vertex_to_node_id1);
|
||||
if (index_p1 != NID)
|
||||
{
|
||||
if (tm1_coplanar_faces.test(get(fids1, f)))
|
||||
{
|
||||
coplanar_patches_of_tm1.set(patch_id);
|
||||
coplanar_patches_of_tm1_for_union_and_intersection.set(patch_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex_descriptor vn = source(halfedge(f, tm1), tm1);
|
||||
Bounded_side other_position = inside_tm2( get(vpm1, vn) );
|
||||
if (other_position==ON_BOUNDARY)
|
||||
{
|
||||
// \todo improve this part which is not robust with a kernel
|
||||
// with inexact constructions.
|
||||
other_position = inside_tm2(midpoint(get(vpm1, vn),
|
||||
get(vpm1, v) ));
|
||||
}
|
||||
if ( other_position == in_tm2 )
|
||||
is_patch_inside_tm2.set(patch_id);
|
||||
}
|
||||
h=next(h, tm1);
|
||||
index_p1 = get_node_id(target(h, tm1), vertex_to_node_id1);
|
||||
}
|
||||
}
|
||||
if (index_p1 != NID)
|
||||
{
|
||||
if (tm1_coplanar_faces.test(f_id))
|
||||
{
|
||||
coplanar_patches_of_tm1.set(patch_id);
|
||||
coplanar_patches_of_tm1_for_union_and_intersection.set(patch_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// triangle which is tangent at its 3 vertices
|
||||
// \todo improve this part which is not robust with a kernel
|
||||
// with inexact constructions.
|
||||
Bounded_side position = inside_tm2(midpoint(get(vpm1, source(h, tm1)),
|
||||
get(vpm1, target(h, tm1)) ));
|
||||
CGAL_assertion( position != ON_BOUNDARY);
|
||||
if ( position == in_tm2 )
|
||||
is_patch_inside_tm2.set(patch_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: tm2 might have been modified and an inexact vpm will
|
||||
// provide a non-robust result.
|
||||
Bounded_side position = inside_tm2( get(vpm1, target(h, tm1)));
|
||||
CGAL_assertion( position != ON_BOUNDARY);
|
||||
if ( position == in_tm2 )
|
||||
is_patch_inside_tm2.set(patch_id);
|
||||
}
|
||||
if ( patch_status_not_set_tm1.none() ) break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1035,37 +1134,51 @@ public:
|
|||
Inside_poly_test inside_tm1(tm1, vpm1);
|
||||
BOOST_FOREACH(face_descriptor f, faces(tm2))
|
||||
{
|
||||
std::size_t patch_id=tm2_patch_ids[ get(fids2, f) ];
|
||||
const std::size_t f_id = get(fids2, f);
|
||||
std::size_t patch_id=tm2_patch_ids[ f_id ];
|
||||
if ( patch_status_not_set_tm2.test( patch_id ) )
|
||||
{
|
||||
patch_status_not_set_tm2.reset( patch_id );
|
||||
vertex_descriptor v = target(halfedge(f, tm2), tm2);
|
||||
Bounded_side position = inside_tm1( get(vpm2, v));
|
||||
if ( position == in_tm1 )
|
||||
is_patch_inside_tm1.set(patch_id);
|
||||
else
|
||||
if( position == ON_BOUNDARY)
|
||||
halfedge_descriptor h = halfedge(f, tm2);
|
||||
Node_id index_p2 = get_node_id(target(h, tm2), vertex_to_node_id2);
|
||||
if (index_p2 != NID)
|
||||
{
|
||||
h=next(h, tm2);
|
||||
index_p2 = get_node_id(target(h, tm2), vertex_to_node_id2);
|
||||
if (index_p2 != NID)
|
||||
{
|
||||
if (tm2_coplanar_faces.test(get(fids2, f)))
|
||||
{
|
||||
coplanar_patches_of_tm2.set(patch_id);
|
||||
coplanar_patches_of_tm2_for_union_and_intersection.set(patch_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex_descriptor vn = source(halfedge(f, tm2), tm2);
|
||||
Bounded_side other_position = inside_tm1( get(vpm2, vn) );
|
||||
if (other_position==ON_BOUNDARY)
|
||||
{
|
||||
// \todo improve this part which is not robust with a kernel
|
||||
// with inexact constructions.
|
||||
other_position = inside_tm1(midpoint(get(vpm2, vn),
|
||||
get(vpm2, v) ));
|
||||
}
|
||||
if ( other_position == in_tm1 )
|
||||
is_patch_inside_tm1.set(patch_id);
|
||||
}
|
||||
h=next(h, tm2);
|
||||
index_p2 = get_node_id(target(h, tm2), vertex_to_node_id2);
|
||||
}
|
||||
}
|
||||
if (index_p2 != NID)
|
||||
{
|
||||
if (tm2_coplanar_faces.test(f_id))
|
||||
{
|
||||
coplanar_patches_of_tm2.set(patch_id);
|
||||
coplanar_patches_of_tm2_for_union_and_intersection.set(patch_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// triangle which is tangent at its 3 vertices
|
||||
// \todo improve this part which is not robust with a kernel
|
||||
// with inexact constructions.
|
||||
Bounded_side position = inside_tm1(midpoint(get(vpm2, source(h, tm2)),
|
||||
get(vpm2, target(h, tm2)) ));
|
||||
CGAL_assertion( position != ON_BOUNDARY);
|
||||
if ( position == in_tm1 )
|
||||
is_patch_inside_tm1.set(patch_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: tm1 might have been modified and an inexact vpm will
|
||||
// provide a non-robust result.
|
||||
Bounded_side position = inside_tm1( get(vpm2, target(h, tm2)));
|
||||
CGAL_assertion( position != ON_BOUNDARY);
|
||||
if ( position == in_tm1 )
|
||||
is_patch_inside_tm1.set(patch_id);
|
||||
}
|
||||
if ( patch_status_not_set_tm2.none() ) break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1436,6 +1549,59 @@ public:
|
|||
patches_of_tm1_used[inplace_operation_tm1],
|
||||
patches_of_tm2_used[inplace_operation_tm1],
|
||||
fids1, fids2, tm1, tm2);
|
||||
|
||||
if (used_to_clip_a_surface)
|
||||
{
|
||||
// The following code is here to handle the case when an intersection polyline
|
||||
// contains some border edges of tm1 that should be considered as an independant polyline.
|
||||
// This polyline removal should be handled by remove_unused_polylines.
|
||||
// However, since all nodes are of degree 2 the polyline is not split at
|
||||
// the correct point and trouble happen. Here the workaround consists in
|
||||
// removing border edges of patches to be removed that are not in a
|
||||
// polyline schedule for removal.
|
||||
boost::dynamic_bitset<> patches_to_remove = ~patches_of_tm1_used[inplace_operation_tm1];
|
||||
for (std::size_t i = patches_to_remove.find_first();
|
||||
i < patches_to_remove.npos;
|
||||
i = patches_to_remove.find_next(i))
|
||||
{
|
||||
typedef typename std::vector<halfedge_descriptor>::iterator Hedge_iterator;
|
||||
std::vector< Hedge_iterator > to_rm;
|
||||
for (Hedge_iterator it = patches_of_tm1[i].shared_edges.begin();
|
||||
it!= patches_of_tm1[i].shared_edges.end();
|
||||
++it)
|
||||
{
|
||||
if ( is_border(opposite(*it, tm1), tm1) )
|
||||
to_rm.push_back(it);
|
||||
}
|
||||
if (!to_rm.empty())
|
||||
{
|
||||
std::reverse(to_rm.begin(), to_rm.end());
|
||||
BOOST_FOREACH(Hedge_iterator it, to_rm)
|
||||
{
|
||||
patches_of_tm1[i].interior_edges.push_back(*it);
|
||||
if (it!=cpp11::prev(patches_of_tm1[i].shared_edges.end()))
|
||||
std::swap(patches_of_tm1[i].shared_edges.back(), *it);
|
||||
patches_of_tm1[i].shared_edges.pop_back();
|
||||
}
|
||||
//now update interior vertices
|
||||
std::set<vertex_descriptor> border_vertices;
|
||||
BOOST_FOREACH(halfedge_descriptor h, patches_of_tm1[i].shared_edges)
|
||||
{
|
||||
border_vertices.insert( target(h,tm1) );
|
||||
border_vertices.insert( source(h,tm1) );
|
||||
}
|
||||
|
||||
BOOST_FOREACH(halfedge_descriptor h, patches_of_tm1[i].interior_edges)
|
||||
{
|
||||
if ( !border_vertices.count( target(h,tm1) ) )
|
||||
patches_of_tm1[i].interior_vertices.insert( target(h,tm1) );
|
||||
if ( !border_vertices.count( source(h,tm1) ) )
|
||||
patches_of_tm1[i].interior_vertices.insert( source(h,tm1) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define CGAL_COREF_FUNCTION_CALL_DEF(BO_type) \
|
||||
compute_inplace_operation( \
|
||||
tm1, tm2, \
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ class Output_builder_for_autorefinement
|
|||
const VertexPointMap &vpm;
|
||||
const FaceIdMap &fids;
|
||||
Ecm& ecm;
|
||||
Node_id_map vertex_to_node_id;
|
||||
// input meshes closed ?
|
||||
bool is_tm_closed;
|
||||
// orientation of input surface mesh
|
||||
|
|
@ -208,6 +209,13 @@ public:
|
|||
all_intersection_edges_map[indices].add(hedge);
|
||||
}
|
||||
|
||||
void set_vertex_id(vertex_descriptor v, Node_id node_id, const TriangleMesh& tm_)
|
||||
{
|
||||
CGAL_USE(tm_);
|
||||
CGAL_assertion(&tm_==&tm);
|
||||
vertex_to_node_id.insert( std::make_pair(v, node_id) );
|
||||
}
|
||||
|
||||
template <class Nodes_vector, class Mesh_to_map_node>
|
||||
void operator()(
|
||||
const Nodes_vector& nodes,
|
||||
|
|
@ -220,7 +228,6 @@ public:
|
|||
|
||||
// first build an unordered_map mapping a vertex to its node id + a set
|
||||
// of all intersection edges
|
||||
Node_id_map vertex_to_node_id;
|
||||
typedef boost::unordered_set<edge_descriptor> Intersection_edge_map;
|
||||
Intersection_edge_map intersection_edges;
|
||||
|
||||
|
|
@ -233,10 +240,10 @@ public:
|
|||
// and will be discarded later
|
||||
if (p.second.h2==boost::graph_traits<TriangleMesh>::null_halfedge())
|
||||
continue;
|
||||
vertex_to_node_id[source(p.second.h1, tm)] = p.first.first;
|
||||
vertex_to_node_id[target(p.second.h1, tm)] = p.first.second;
|
||||
vertex_to_node_id[source(p.second.h2, tm)] = p.first.first;
|
||||
vertex_to_node_id[target(p.second.h2, tm)] = p.first.second;
|
||||
CGAL_assertion( vertex_to_node_id[source(p.second.h1, tm)] == p.first.first);
|
||||
CGAL_assertion( vertex_to_node_id[target(p.second.h1, tm)] == p.first.second);
|
||||
CGAL_assertion( vertex_to_node_id[source(p.second.h2, tm)] == p.first.first);
|
||||
CGAL_assertion( vertex_to_node_id[target(p.second.h2, tm)] == p.first.second);
|
||||
intersection_edges.insert(edge(p.second.h1, tm));
|
||||
intersection_edges.insert(edge(p.second.h2, tm));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ struct No_extra_output_from_corefinement
|
|||
void set_edge_per_polyline(G& /*tm*/,
|
||||
Node_id_pair /*indices*/,
|
||||
halfedge_descriptor /*hedge*/){}
|
||||
template <class vertex_descriptor, class Node_id>
|
||||
void set_vertex_id(vertex_descriptor, Node_id, const G&){}
|
||||
template <class Node_vector,
|
||||
class Mesh_to_map_node>
|
||||
void operator()(
|
||||
|
|
@ -360,6 +362,7 @@ public:
|
|||
node_id_to_vertex[node_id]=target(h_2,tm2);
|
||||
all_incident_faces_got_a_node_as_vertex(h_2,node_id,*tm2_ptr);
|
||||
// check_node_on_non_manifold_vertex(node_id,h_2,tm2);
|
||||
output_builder.set_vertex_id(target(h_2, tm2), node_id, tm2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -377,6 +380,8 @@ public:
|
|||
node_id_to_vertex.resize(node_id+1,Graph_traits::null_vertex());
|
||||
node_id_to_vertex[node_id]=target(h_1,tm1);
|
||||
all_incident_faces_got_a_node_as_vertex(h_1,node_id, *tm1_ptr);
|
||||
// register the vertex in the output builder
|
||||
output_builder.set_vertex_id(target(h_1, tm1), node_id, tm1);
|
||||
// check_node_on_non_manifold_vertex(node_id,h_1,tm1);
|
||||
}
|
||||
else{
|
||||
|
|
@ -389,6 +394,8 @@ public:
|
|||
node_id_to_vertex.resize(node_id+1,Graph_traits::null_vertex());
|
||||
node_id_to_vertex[node_id]=source(h_1,tm1);
|
||||
all_incident_faces_got_a_node_as_vertex(h_1_opp,node_id, *tm1_ptr);
|
||||
// register the vertex in the output builder
|
||||
output_builder.set_vertex_id(source(h_1, tm1), node_id, tm1);
|
||||
// check_node_on_non_manifold_vertex(node_id,h_1_opp,tm1);
|
||||
}
|
||||
else{
|
||||
|
|
@ -753,7 +760,8 @@ public:
|
|||
vertex_descriptor vnew=target(hnew,tm);
|
||||
// user_visitor.new_vertex_added(node_id, vnew, tm); // NODE_VISITOR_TAG
|
||||
nodes.call_put(vpm, vnew, node_id, tm);
|
||||
|
||||
// register the new vertex in the output builder
|
||||
output_builder.set_vertex_id(vnew, node_id, tm);
|
||||
node_id_to_vertex[node_id]=vnew;
|
||||
if (first){
|
||||
first=false;
|
||||
|
|
@ -997,7 +1005,7 @@ public:
|
|||
|
||||
// import the triangle in `cdt` in the face `f` of `tm`
|
||||
triangulate_a_face(f, tm, nodes, node_ids, node_id_to_vertex,
|
||||
edge_to_hedge, cdt, vpm, user_visitor);
|
||||
edge_to_hedge, cdt, vpm, output_builder, user_visitor);
|
||||
|
||||
// TODO Here we do the update only for internal edges.
|
||||
// Update for border halfedges could be done during the split
|
||||
|
|
|
|||
|
|
@ -263,6 +263,7 @@ template < class TriangleMesh,
|
|||
class Node_id,
|
||||
class Node_vector,
|
||||
class CDT,
|
||||
class OutputBuilder,
|
||||
class UserVisitor>
|
||||
void
|
||||
triangulate_a_face(
|
||||
|
|
@ -277,6 +278,7 @@ triangulate_a_face(
|
|||
::halfedge_descriptor>& edge_to_hedge,
|
||||
const CDT& cdt,
|
||||
const VertexPointMap& vpm,
|
||||
OutputBuilder& output_builder,
|
||||
UserVisitor& user_visitor)
|
||||
{
|
||||
typedef boost::graph_traits<TriangleMesh> GT;
|
||||
|
|
@ -292,6 +294,9 @@ triangulate_a_face(
|
|||
vertex_descriptor v=add_vertex(tm);
|
||||
// user_visitor.new_vertex_added(node_id, v, tm); // NODE_VISITOR_TAG
|
||||
nodes.call_put(vpm, v, node_id, tm);
|
||||
// register the new vertex in the output builder
|
||||
output_builder.set_vertex_id(v, node_id, tm);
|
||||
|
||||
CGAL_assertion(node_id_to_vertex.size()>node_id);
|
||||
node_id_to_vertex[node_id]=v;
|
||||
}
|
||||
|
|
@ -378,12 +383,10 @@ triangulate_a_face(
|
|||
|
||||
template <class PolygonMesh>
|
||||
class Border_edge_map {
|
||||
typedef std::size_t Node_id;
|
||||
typedef boost::graph_traits<PolygonMesh> GT;
|
||||
typedef typename GT::halfedge_descriptor halfedge_descriptor;
|
||||
typedef typename GT::edge_descriptor edge_descriptor;
|
||||
typedef boost::unordered_map<edge_descriptor,
|
||||
std::pair<Node_id,Node_id> > Intersection_edge_map;
|
||||
typedef boost::unordered_set<edge_descriptor> Intersection_edge_map;
|
||||
const Intersection_edge_map* intersection_edges;
|
||||
const PolygonMesh* tm;
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -900,9 +900,53 @@ bool remove_degenerate_faces( TriangleMesh& tmesh,
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Then, remove triangles made of 3 collinear points
|
||||
std::set<face_descriptor> degenerate_face_set;
|
||||
degenerate_faces(tmesh, std::inserter(degenerate_face_set, degenerate_face_set.begin()), np);
|
||||
|
||||
// start by filtering out border faces
|
||||
std::set<face_descriptor> border_deg_faces;
|
||||
BOOST_FOREACH(face_descriptor f, degenerate_face_set)
|
||||
{
|
||||
halfedge_descriptor h = halfedge(f, tmesh);
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
if ( is_border( opposite(h, tmesh), tmesh) )
|
||||
{
|
||||
border_deg_faces.insert(f);
|
||||
break;
|
||||
}
|
||||
h = next(h, tmesh);
|
||||
}
|
||||
}
|
||||
|
||||
while( !border_deg_faces.empty() )
|
||||
{
|
||||
face_descriptor f_to_rm = *border_deg_faces.begin();
|
||||
border_deg_faces.erase(border_deg_faces.begin());
|
||||
|
||||
halfedge_descriptor h = halfedge(f_to_rm, tmesh);
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
if (is_border(h, tmesh) )
|
||||
{
|
||||
face_descriptor f = face(opposite(h, tmesh), tmesh);
|
||||
if (is_degenerate_triangle_face(f, tmesh, np) )
|
||||
border_deg_faces.insert(f);
|
||||
}
|
||||
h = next(h, tmesh);
|
||||
}
|
||||
|
||||
while( !is_border(opposite(h, tmesh), tmesh) )
|
||||
{
|
||||
h = next(h, tmesh);
|
||||
}
|
||||
|
||||
degenerate_face_set .erase(f_to_rm);
|
||||
Euler::remove_face(h, tmesh);
|
||||
}
|
||||
|
||||
// Ignore faces with null edges
|
||||
if (!all_removed)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
OFF
|
||||
6 8 0
|
||||
-0.98999999999999977 10 0.99999999999999978
|
||||
-0.98999999999999999 -2.4671622769447923e-19 2.4671622769447923e-19
|
||||
-0.98999999999999999 10 10
|
||||
-0.99999999999999978 10 0.99999999999999978
|
||||
-1 0 0
|
||||
-1 10 10
|
||||
3 2 0 1
|
||||
3 4 3 5
|
||||
3 5 3 0
|
||||
3 0 2 5
|
||||
3 3 4 1
|
||||
3 1 0 3
|
||||
3 4 5 2
|
||||
3 2 1 4
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
OFF
|
||||
9 8 0
|
||||
-0.99999999999999978 10 0.99999999999999978
|
||||
-10 0 1
|
||||
0 0 1
|
||||
-1 0 1
|
||||
-0.98999999999999999 1 1
|
||||
-0.98999999999999999 1.1102230246251566e-19 1
|
||||
-0.99899999999999989 1.1102230246251564e-20 1
|
||||
-0.99099999999999988 1 1
|
||||
-1 1 1
|
||||
3 0 8 7
|
||||
3 0 1 8
|
||||
3 8 1 3
|
||||
3 0 4 2
|
||||
3 5 6 2
|
||||
3 4 5 2
|
||||
3 6 3 2
|
||||
3 0 7 4
|
||||
|
|
@ -216,6 +216,73 @@ void test()
|
|||
PMP::clip(tm1, K::Plane_3(-1, 0, 0, 2));
|
||||
assert(vertices(tm1).size()==3);
|
||||
CGAL::clear(tm1);
|
||||
|
||||
// test with clipper on border edge
|
||||
make_triangle( K::Point_3(0, 0, 0), K::Point_3(0, 1, 0), K::Point_3(1, 0, 0), tm1 );
|
||||
PMP::clip(tm1, K::Plane_3(0, 1, 0 , 0));
|
||||
assert(vertices(tm1).size()==0);
|
||||
CGAL::clear(tm1);
|
||||
|
||||
make_triangle( K::Point_3(0, 0, 0), K::Point_3(0, 1, 0), K::Point_3(1, 0, 0), tm1 );
|
||||
PMP::clip(tm1, K::Plane_3(0, -1, 0 , 0));
|
||||
assert(vertices(tm1).size()==4);
|
||||
CGAL::clear(tm1);
|
||||
|
||||
// test with clipper on border edge: full triangle
|
||||
make_triangle( K::Point_3(0, 0, 0), K::Point_3(0, 4, 0), K::Point_3(4, 0, 0), tm1 );
|
||||
PMP::clip(tm1, K::Plane_3(0, 0, 1, 0), params::use_compact_clipper(true));
|
||||
assert(vertices(tm1).size()!=0);
|
||||
CGAL::clear(tm1);
|
||||
|
||||
make_triangle( K::Point_3(0, 0, 0), K::Point_3(0, 4, 0), K::Point_3(4, 0, 0), tm1 );
|
||||
PMP::clip(tm1, K::Plane_3(0, 0, 1, 0), params::use_compact_clipper(false));
|
||||
assert(vertices(tm1).size()==0);
|
||||
CGAL::clear(tm1);
|
||||
|
||||
// test tangencies
|
||||
make_triangle( K::Point_3(0, 0, 0), K::Point_3(0, 2, 0), K::Point_3(1, 1, 0), tm1 );
|
||||
PMP::clip(tm1, K::Plane_3(1, 0, 0, -1));
|
||||
assert(vertices(tm1).size()==3);
|
||||
CGAL::clear(tm1);
|
||||
|
||||
make_triangle( K::Point_3(0, 0, 0), K::Point_3(0, 2, 0), K::Point_3(1, 1, 0), tm1 );
|
||||
PMP::clip(tm1, K::Plane_3(-1, 0, 0, 1));
|
||||
assert(vertices(tm1).size()==0);
|
||||
CGAL::clear(tm1);
|
||||
|
||||
make_triangle( K::Point_3(0.5, 0, 0.5), K::Point_3(1, 0.5, 0.5), K::Point_3(0.5, 1, 0.5), tm1 );
|
||||
input.open("data-coref/cube.off");
|
||||
input >> tm2;
|
||||
input.close();
|
||||
PMP::clip(tm1, tm2, params::face_index_map(get(CGAL::dynamic_face_property_t<std::size_t>(), tm1)),
|
||||
params::face_index_map(get(CGAL::dynamic_face_property_t<std::size_t>(), tm2)));
|
||||
assert(vertices(tm1).size()==3);
|
||||
CGAL::clear(tm1);
|
||||
CGAL::clear(tm2);
|
||||
|
||||
make_triangle( K::Point_3(0.5, 0, 0.5), K::Point_3(1, 0.5, 0.5), K::Point_3(0.5, 1, 0.5), tm1 );
|
||||
input.open("data-coref/cube.off");
|
||||
input >> tm2;
|
||||
input.close();
|
||||
PMP::reverse_face_orientations(tm2);
|
||||
PMP::clip(tm1, tm2, params::face_index_map(get(CGAL::dynamic_face_property_t<std::size_t>(), tm1)),
|
||||
params::face_index_map(get(CGAL::dynamic_face_property_t<std::size_t>(), tm2)));
|
||||
assert(vertices(tm1).size()==0);
|
||||
CGAL::clear(tm1);
|
||||
CGAL::clear(tm2);
|
||||
|
||||
// test special case
|
||||
input.open("data-clip/tm_1.off");
|
||||
input >> tm1;
|
||||
input.close();
|
||||
input.open("data-clip/clipper_1.off");
|
||||
input >> tm2;
|
||||
input.close();
|
||||
PMP::clip(tm1, tm2, params::face_index_map(get(CGAL::dynamic_face_property_t<std::size_t>(), tm1)),
|
||||
params::face_index_map(get(CGAL::dynamic_face_property_t<std::size_t>(), tm2)));
|
||||
assert(is_valid_polygon_mesh(tm1));
|
||||
CGAL::clear(tm1);
|
||||
CGAL::clear(tm2);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
#include <CGAL/Three/exceptions.h>
|
||||
#include <CGAL/Qt/debug.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QtDebug>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QSettings>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
|
|
@ -37,9 +37,11 @@
|
|||
#include <QDockWidget>
|
||||
#include <QSpinBox>
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
#include <QTime>
|
||||
#include <QWidgetAction>
|
||||
#include <QJsonArray>
|
||||
|
||||
#ifdef QT_SCRIPT_LIB
|
||||
# include <QScriptValue>
|
||||
# ifdef QT_SCRIPTTOOLS_LIB
|
||||
|
|
@ -137,6 +139,7 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren
|
|||
: CGAL::Qt::DemosMainWindow(parent),
|
||||
accepted_keywords(keywords)
|
||||
{
|
||||
bbox_need_update = true;
|
||||
ui = new Ui::MainWindow;
|
||||
ui->setupUi(this);
|
||||
menuBar()->setNativeMenuBar(false);
|
||||
|
|
@ -212,7 +215,7 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren
|
|||
this, SLOT(removeManipulatedFrame(CGAL::Three::Scene_item*)));
|
||||
|
||||
connect(scene, SIGNAL(updated_bbox(bool)),
|
||||
this, SLOT(updateViewersBboxes(bool)));
|
||||
this, SLOT(invalidate_bbox(bool)));
|
||||
|
||||
connect(scene, SIGNAL(selectionChanged(int)),
|
||||
this, SLOT(selectSceneItem(int)));
|
||||
|
|
@ -915,6 +918,8 @@ void MainWindow::error(QString text) {
|
|||
|
||||
void MainWindow::updateViewersBboxes(bool recenter)
|
||||
{
|
||||
if(bbox_need_update)
|
||||
{
|
||||
CGAL::qglviewer::Vec min, max;
|
||||
computeViewerBBox(min, max);
|
||||
Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool())
|
||||
|
|
@ -924,6 +929,8 @@ void MainWindow::updateViewersBboxes(bool recenter)
|
|||
Viewer* vi = static_cast<Viewer*>(v);
|
||||
updateViewerBbox(vi, recenter, min, max);
|
||||
}
|
||||
bbox_need_update = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -936,24 +943,28 @@ void MainWindow::computeViewerBBox(CGAL::qglviewer::Vec& min, CGAL::qglviewer::V
|
|||
const double xmax = bbox.xmax();
|
||||
const double ymax = bbox.ymax();
|
||||
const double zmax = bbox.zmax();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
min = CGAL::qglviewer::Vec(xmin, ymin, zmin);
|
||||
max= CGAL::qglviewer::Vec(xmax, ymax, zmax);
|
||||
|
||||
|
||||
CGAL::qglviewer::Vec bbox_center((xmin+xmax)/2, (ymin+ymax)/2, (zmin+zmax)/2);
|
||||
|
||||
|
||||
CGAL::qglviewer::Vec offset(0,0,0);
|
||||
|
||||
|
||||
double l_dist = (std::max)((std::abs)(bbox_center.x - viewer->offset().x),
|
||||
(std::max)((std::abs)(bbox_center.y - viewer->offset().y),
|
||||
(std::abs)(bbox_center.z - viewer->offset().z)));
|
||||
if((std::log2)(l_dist) > 13.0 )
|
||||
for(int i=0; i<3; ++i)
|
||||
{
|
||||
offset[i] = -bbox_center[i];
|
||||
|
||||
viewer->setOffset(offset);
|
||||
for(int i=0; i<scene->numberOfEntries(); ++i)
|
||||
{
|
||||
scene->item(i)->invalidateOpenGLBuffers();
|
||||
scene->item(i)->itemChanged();
|
||||
}
|
||||
}
|
||||
if(offset != viewer->offset())
|
||||
{
|
||||
|
|
@ -1147,6 +1158,7 @@ void MainWindow::open(QString filename)
|
|||
qobject_cast<CGAL::Three::Scene_group_item*>(scene_item);
|
||||
if(group)
|
||||
scene->redraw_model();
|
||||
updateViewersBboxes(true);
|
||||
}
|
||||
|
||||
bool MainWindow::open(QString filename, QString loader_name) {
|
||||
|
|
@ -1645,7 +1657,6 @@ void MainWindow::updateDisplayInfo() {
|
|||
|
||||
void MainWindow::readSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
viewer->setAntiAliasing(settings.value("antialiasing", false).toBool());
|
||||
viewer->setFastDrawing(settings.value("quick_camera_mode", true).toBool());
|
||||
scene->enableVisibilityRecentering(settings.value("offset_update", true).toBool());
|
||||
|
|
@ -1668,7 +1679,6 @@ void MainWindow::writeSettings()
|
|||
{
|
||||
this->writeState("MainWindow");
|
||||
{
|
||||
QSettings settings;
|
||||
//setting plugin blacklist
|
||||
QStringList blacklist;
|
||||
Q_FOREACH(QString name,plugin_blacklist){ blacklist << name; }
|
||||
|
|
@ -1996,13 +2006,16 @@ void MainWindow::on_actionDuplicate_triggered()
|
|||
|
||||
void MainWindow::on_actionShowHide_triggered()
|
||||
{
|
||||
scene->setUpdatesEnabled(false);
|
||||
Q_FOREACH(QModelIndex index, sceneView->selectionModel()->selectedRows())
|
||||
{
|
||||
int i = scene->getIdFromModelIndex(proxyModel->mapToSource(index));
|
||||
CGAL::Three::Scene_item* item = scene->item(i);
|
||||
item->setVisible(!item->visible());
|
||||
scene->itemChanged(i);
|
||||
item->redraw();
|
||||
}
|
||||
scene->setUpdatesEnabled(true);
|
||||
updateViewersBboxes(false);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSetPolyhedronA_triggered()
|
||||
|
|
@ -2021,7 +2034,6 @@ void MainWindow::on_actionPreferences_triggered()
|
|||
{
|
||||
QDialog dialog(this);
|
||||
Ui::PreferencesDialog prefdiag;
|
||||
QSettings settings;
|
||||
prefdiag.setupUi(&dialog);
|
||||
|
||||
float lineWidth[2];
|
||||
|
|
@ -2276,6 +2288,8 @@ void MainWindow::setAddKeyFrameKeyboardModifiers(::Qt::KeyboardModifiers m)
|
|||
|
||||
void MainWindow::on_actionRecenterScene_triggered()
|
||||
{
|
||||
//force the recomputaion of the bbox
|
||||
bbox_need_update = true;
|
||||
CGAL::qglviewer::Vec min, max;
|
||||
computeViewerBBox(min, max);
|
||||
Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool())
|
||||
|
|
@ -2600,6 +2614,86 @@ void MainWindow::propagate_action()
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSa_ve_Scene_as_Script_triggered()
|
||||
{
|
||||
QString filename =
|
||||
QFileDialog::getSaveFileName(this,
|
||||
"Save the Scene as a Script File",
|
||||
last_saved_dir,
|
||||
"Qt Script files (*.js)");
|
||||
std::ofstream os(filename.toUtf8());
|
||||
if(!os)
|
||||
return;
|
||||
std::vector<QString> names;
|
||||
std::vector<QString> loaders;
|
||||
std::vector<QColor> colors;
|
||||
std::vector<int> rendering_modes;
|
||||
QStringList not_saved;
|
||||
for(int i = 0; i < scene->numberOfEntries(); ++i)
|
||||
{
|
||||
Scene_item* item = scene->item(i);
|
||||
QString loader = item->property("loader_name").toString();
|
||||
QString source = item->property("source filename").toString();
|
||||
if(loader.isEmpty())
|
||||
{
|
||||
not_saved.push_back(item->name());
|
||||
continue;
|
||||
}
|
||||
names.push_back(source);
|
||||
loaders.push_back(loader);
|
||||
colors.push_back(item->color());
|
||||
rendering_modes.push_back(item->renderingMode());
|
||||
}
|
||||
//path
|
||||
os << "var camera = \""<<viewer->dumpCameraCoordinates().toStdString()<<"\";\n";
|
||||
os << "var items = [";
|
||||
for(std::size_t i = 0; i< names.size() -1; ++i)
|
||||
{
|
||||
os << "\'" << names[i].toStdString() << "\', ";
|
||||
}
|
||||
os<<"\'"<<names.back().toStdString()<<"\'];\n";
|
||||
|
||||
//plugin
|
||||
os << "var loaders = [";
|
||||
for(std::size_t i = 0; i< names.size() -1; ++i)
|
||||
{
|
||||
os << "\'" << loaders[i].toStdString() << "\', ";
|
||||
}
|
||||
os<<"\'"<<loaders.back().toStdString()<<"\'];\n";
|
||||
|
||||
//color
|
||||
os << "var colors = [";
|
||||
for(std::size_t i = 0; i< names.size() -1; ++i)
|
||||
{
|
||||
os << "[" << colors[i].red() <<", "<< colors[i].green() <<", "<< colors[i].blue() <<"], ";
|
||||
}
|
||||
os<<"[" << colors.back().red() <<", "<< colors.back().green() <<", "<< colors.back().blue() <<"]];\n";
|
||||
|
||||
//rendering mode
|
||||
os << "var rendering_modes = [";
|
||||
for(std::size_t i = 0; i< names.size() -1; ++i)
|
||||
{
|
||||
os << rendering_modes[i] << ", ";
|
||||
}
|
||||
os << rendering_modes.back()<<"];\n";
|
||||
os <<"var initial_scene_size = scene.numberOfEntries;\n";
|
||||
os << "items.forEach(function(item, index, array){\n";
|
||||
os << " main_window.open(item, loaders[index]);\n";
|
||||
os << " var it = scene.item(initial_scene_size+index);\n";
|
||||
os << " var r = colors[index][0];\n";
|
||||
os << " var g = colors[index][1];\n";
|
||||
os << " var b = colors[index][2];\n";
|
||||
os << " it.setRgbColor(r,g,b);\n";
|
||||
os << " it.setRenderingMode(rendering_modes[index]);\n";
|
||||
os << "});\n";
|
||||
os << "viewer.moveCameraToCoordinates(camera, 0.05);\n";
|
||||
os.close();
|
||||
if(!not_saved.empty())
|
||||
QMessageBox::warning(this,
|
||||
"Items Not Saved",
|
||||
QString("The following items could not be saved: %1").arg(
|
||||
not_saved.join(", ")));
|
||||
}
|
||||
void MainWindow::setTransparencyPasses(int val)
|
||||
{
|
||||
viewer->setTotalPass(val);
|
||||
|
|
@ -2635,9 +2729,10 @@ void MainWindow::setDefaultSaveDir()
|
|||
QString dirpath = QFileDialog::getExistingDirectory(this, "Set Default Save as Directory", def_save_dir);
|
||||
if(!dirpath.isEmpty())
|
||||
def_save_dir = dirpath;
|
||||
QSettings settings;
|
||||
settings.setValue("default_saveas_dir", def_save_dir);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::setupViewer(Viewer* viewer, SubViewer* subviewer)
|
||||
{
|
||||
// do not save the state of the viewer (anoying)
|
||||
|
|
@ -2765,7 +2860,6 @@ void MainWindow::recenterViewer()
|
|||
void MainWindow::updateViewerBbox(Viewer *vi, bool recenter,
|
||||
CGAL::qglviewer::Vec min,
|
||||
CGAL::qglviewer::Vec max){
|
||||
|
||||
CGAL::qglviewer::Vec center = viewer->camera()->pivotPoint();
|
||||
vi->setSceneBoundingBox(min,
|
||||
max);
|
||||
|
|
@ -2962,3 +3056,10 @@ void SubViewer::changeEvent(QEvent *event)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::invalidate_bbox(bool do_recenter)
|
||||
{
|
||||
bbox_need_update = true;
|
||||
if(do_recenter)
|
||||
updateViewersBboxes(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -446,14 +446,17 @@ public:
|
|||
const QString & fileName = QString());
|
||||
#endif
|
||||
public Q_SLOTS:
|
||||
void on_actionSa_ve_Scene_as_Script_triggered();
|
||||
void toggleFullScreen();
|
||||
void setDefaultSaveDir();
|
||||
void invalidate_bbox(bool do_recenter);
|
||||
private:
|
||||
SubViewer* viewer_window;
|
||||
QList<QDockWidget *> visibleDockWidgets;
|
||||
QLineEdit operationSearchBar;
|
||||
QWidgetAction* searchAction;
|
||||
QString def_save_dir;
|
||||
bool bbox_need_update;
|
||||
QMap<QString, QPair<QStringList, QString> >plugin_metadata_map;
|
||||
QMap<QString, bool> ignored_map;
|
||||
const QStringList& accepted_keywords;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
<addaction name="actionEraseAll"/>
|
||||
<addaction name="actionDuplicate"/>
|
||||
<addaction name="actionSaveAs"/>
|
||||
<addaction name="actionSa_ve_Scene_as_Script"/>
|
||||
<addaction name="actionSaveSnapshot"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionLoadScript"/>
|
||||
|
|
@ -460,6 +461,11 @@
|
|||
<string>Ctrl+R</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSa_ve_Scene_as_Script">
|
||||
<property name="text">
|
||||
<string>Sa&ve the Scene as a Script File...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="Polyhedron_3.qrc"/>
|
||||
|
|
|
|||
|
|
@ -500,7 +500,8 @@ void Mesh_3_plugin::mesh_3(const bool surface_only, const bool use_defaults)
|
|||
tet_sizing,
|
||||
edge_size,
|
||||
radius_edge,
|
||||
manifold);
|
||||
manifold,
|
||||
surface_only);
|
||||
}
|
||||
#endif
|
||||
#ifdef CGAL_MESH_3_DEMO_ACTIVATE_SEGMENTED_IMAGES
|
||||
|
|
@ -525,6 +526,7 @@ void Mesh_3_plugin::mesh_3(const bool surface_only, const bool use_defaults)
|
|||
radius_edge,
|
||||
protect_features,
|
||||
manifold,
|
||||
surface_only,
|
||||
detect_connected_components,
|
||||
image_item->isGray(),
|
||||
iso_value,
|
||||
|
|
|
|||
|
|
@ -176,7 +176,8 @@ Meshing_thread* cgal_code_mesh_3(const Implicit_function_interface* pfunction,
|
|||
const double tet_sizing,
|
||||
const double edge_size,
|
||||
const double tet_shape,
|
||||
const int manifold)
|
||||
const int manifold,
|
||||
const bool surface_only)
|
||||
{
|
||||
if (pfunction == NULL) { return NULL; }
|
||||
|
||||
|
|
@ -193,7 +194,8 @@ Meshing_thread* cgal_code_mesh_3(const Implicit_function_interface* pfunction,
|
|||
[](int i, int j) { return (i * 1000 + j); }
|
||||
);
|
||||
|
||||
Scene_c3t3_item* p_new_item = new Scene_c3t3_item;
|
||||
Scene_c3t3_item* p_new_item = new Scene_c3t3_item(surface_only);
|
||||
|
||||
Mesh_parameters param;
|
||||
param.protect_features = false;
|
||||
param.facet_angle = facet_angle;
|
||||
|
|
@ -229,6 +231,7 @@ Meshing_thread* cgal_code_mesh_3(const Image* pImage,
|
|||
const double tet_shape,
|
||||
bool protect_features,
|
||||
const int manifold,
|
||||
const bool surface_only,
|
||||
bool detect_connected_components,
|
||||
bool is_gray,
|
||||
float iso_value,
|
||||
|
|
@ -251,7 +254,7 @@ Meshing_thread* cgal_code_mesh_3(const Image* pImage,
|
|||
param.tet_shape = tet_shape;
|
||||
param.manifold = manifold;
|
||||
param.image_3_ptr = pImage;
|
||||
Scene_c3t3_item* p_new_item = new Scene_c3t3_item;
|
||||
Scene_c3t3_item* p_new_item = new Scene_c3t3_item(surface_only);
|
||||
if(!is_gray)
|
||||
{
|
||||
namespace p = CGAL::parameters;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ Meshing_thread* cgal_code_mesh_3(const Implicit_function_interface* pfunction,
|
|||
const double tet_sizing,
|
||||
const double edge_size,
|
||||
const double tet_shape,
|
||||
const int manifold);
|
||||
const int manifold,
|
||||
const bool surface_only);
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_MESH_3_DEMO_ACTIVATE_SEGMENTED_IMAGES
|
||||
|
|
@ -56,6 +57,7 @@ Meshing_thread* cgal_code_mesh_3(const CGAL::Image_3* pImage,
|
|||
const double tet_shape,
|
||||
bool protect_features,
|
||||
const int manifold,
|
||||
const bool surface_only,
|
||||
bool detect_connected_components,
|
||||
bool is_gray = false,
|
||||
float iso_value = 3.f,
|
||||
|
|
|
|||
|
|
@ -130,9 +130,9 @@ public:
|
|||
else { it->polyline->setWidth(3); }
|
||||
|
||||
if(selected_holes.find(it) != selected_holes.end())
|
||||
{ it->polyline->setRbgColor(255, 0, 0); }
|
||||
{ it->polyline->setRgbColor(255, 0, 0); }
|
||||
else
|
||||
{ it->polyline->setRbgColor(0, 0, 255); }
|
||||
{ it->polyline->setRgbColor(0, 0, 255); }
|
||||
|
||||
it->polyline->drawEdges(viewer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ private:
|
|||
g = static_cast<unsigned char>(64 + rand.get_int(0, 192));
|
||||
b = static_cast<unsigned char>(64 + rand.get_int(0, 192));
|
||||
|
||||
point_item->setRbgColor(r, g, b);
|
||||
point_item->setRgbColor(r, g, b);
|
||||
|
||||
std::size_t nb_colored_pts = 0;
|
||||
if (dialog.generate_colored_point_set())
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ Scene::Scene(QObject* parent)
|
|||
this, SLOT(adjustIds(Scene_interface::Item_id)));
|
||||
picked = false;
|
||||
gl_init = false;
|
||||
dont_emit_changes = false;
|
||||
|
||||
}
|
||||
Scene::Item_id
|
||||
|
|
@ -1298,14 +1299,23 @@ void Scene::itemChanged()
|
|||
|
||||
void Scene::itemChanged(Item_id i)
|
||||
{
|
||||
if(i < 0 || i >= m_entries.size())
|
||||
return;
|
||||
if(dont_emit_changes)
|
||||
return;
|
||||
if(i < 0 || i >= m_entries.size())
|
||||
return;
|
||||
|
||||
Q_EMIT dataChanged(this->createIndex(i, 0),
|
||||
this->createIndex(i, LastColumn));
|
||||
}
|
||||
|
||||
void Scene::itemChanged(CGAL::Three::Scene_item*)
|
||||
void Scene::itemChanged(CGAL::Three::Scene_item*item )
|
||||
{
|
||||
if(dont_emit_changes)
|
||||
return;
|
||||
itemChanged(item_id(item));
|
||||
}
|
||||
|
||||
void Scene::allItemsChanged()
|
||||
{
|
||||
Q_EMIT dataChanged(this->createIndex(0, 0),
|
||||
this->createIndex(m_entries.size() - 1, LastColumn));
|
||||
|
|
@ -1324,8 +1334,10 @@ void Scene::itemVisibilityChanged(CGAL::Three::Scene_item* item)
|
|||
&& !item->isEmpty())
|
||||
{
|
||||
//does not recenter
|
||||
if(visibility_recentering_enabled)
|
||||
Q_EMIT updated_bbox(false);
|
||||
if(visibility_recentering_enabled){
|
||||
Q_EMIT updated_bbox(true);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,13 @@ public:
|
|||
|
||||
void zoomToPosition(QPoint point,
|
||||
CGAL::Three::Viewer_interface*) Q_DECL_OVERRIDE;
|
||||
|
||||
void setUpdatesEnabled(bool b) Q_DECL_OVERRIDE
|
||||
{
|
||||
dont_emit_changes = b;
|
||||
if(b)
|
||||
allItemsChanged();
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
//!Specifies a group as Expanded for the Geometric Objects view
|
||||
void setExpanded(QModelIndex);
|
||||
|
|
@ -151,6 +157,7 @@ public Q_SLOTS:
|
|||
void itemChanged();
|
||||
void itemChanged(int i) Q_DECL_OVERRIDE;
|
||||
void itemChanged(CGAL::Three::Scene_item*) Q_DECL_OVERRIDE;
|
||||
void allItemsChanged() Q_DECL_OVERRIDE;
|
||||
//!Transmits a CGAL::Three::Scene_item::itemVisibilityChanged() signal to the scene.
|
||||
void itemVisibilityChanged();
|
||||
void itemVisibilityChanged(CGAL::Three::Scene_item*) Q_DECL_OVERRIDE;
|
||||
|
|
@ -291,6 +298,8 @@ private:
|
|||
QMap<CGAL::Three::Viewer_interface*, QOpenGLVertexArrayObject*> vaos;
|
||||
mutable QOpenGLBuffer vbo[2];
|
||||
Bbox last_bbox;
|
||||
//the scene will ignore the itemChanged() signals while this is true.
|
||||
bool dont_emit_changes;
|
||||
bool visibility_recentering_enabled;
|
||||
bool sort_lists(QVector<QList<int> >&sorted_lists, bool up);
|
||||
}; // end class Scene
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ void check_types(output out){
|
|||
CGAL_USE_TYPE(typename output::pointer);
|
||||
CGAL_USE_TYPE(typename output::reference);
|
||||
T1 tmp=out.get_iterator_tuple();
|
||||
tmp=tmp;
|
||||
tmp=(T1&)tmp;
|
||||
}
|
||||
|
||||
template <class T1,class T2>
|
||||
|
|
@ -69,8 +69,8 @@ void complete_test(std::vector<T1> data1,std::list<T2> data2){
|
|||
check_types(disp);
|
||||
check_types(drop);
|
||||
|
||||
disp = disp;
|
||||
drop = drop;
|
||||
disp = (Dispatcher&)disp;
|
||||
drop = (Dropper&)drop;
|
||||
|
||||
std::back_insert_iterator<std::vector<T2> > bck_ins(cont_2);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,17 +14,17 @@ function reset() {
|
|||
|
||||
trap reset ERR EXIT KILL TERM INT
|
||||
|
||||
for c in $(git log --pretty='%h' --first-parent cgal/master..$base); do
|
||||
for c in $(git --no-pager log --pretty='%h' --first-parent cgal/master..$base); do
|
||||
git update-ref refs/cgal/git-show-content $c
|
||||
git bundle create bundle ${c}^..refs/cgal/git-show-content > /dev/null 2>&1
|
||||
gzip -f bundle
|
||||
size=${(l:4:)$(( $(zstat +size bundle.gz) / 1024 ))}
|
||||
git show --no-patch --pretty='%C(auto)%h (SIZE: %C(auto)'"${size}kB)"' %s <%an> %cD' $c
|
||||
git --no-pager show --no-patch --pretty='%C(auto)%h (SIZE: %C(auto)'"${size}kB)"' %s <%an> %cD' $c
|
||||
parents=(${(@)$(git rev-parse $c^@)})
|
||||
if ! [ ${#${parents:1}[@]} -eq 0 ]; then
|
||||
git show --no-patch --pretty=' merge: %h%C(auto)% d' ${parents:1}
|
||||
git --no-pager show --no-patch --pretty=' merge: %h%C(auto)% d' ${parents:1}
|
||||
fi
|
||||
done
|
||||
last=$c
|
||||
|
||||
[ -n "$last" ] && git log -1 --pretty='Base commit: %C(auto)%h %d' ${last}'~'
|
||||
[ -n "$last" ] && git --no-pager log -1 --pretty='Base commit: %C(auto)%h %d' ${last}'~'
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ bool test_sdg(InputStream&, const SDG&, const char* ifname, const char* ofname,
|
|||
start_testing("assignment operator");
|
||||
sdg.insert(site_list.begin(), site_list.end());
|
||||
|
||||
sdg = sdg;
|
||||
sdg = (Segment_Delaunay_graph_2&)sdg;
|
||||
sdg2 = sdg;
|
||||
|
||||
assert( sdg.is_valid() );
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ bool test_sdg(InputStream&, const SDG&, const char* ifname, const char* ofname,
|
|||
start_testing("assignment operator");
|
||||
sdg.insert(site_list.begin(), site_list.end());
|
||||
|
||||
sdg = sdg;
|
||||
sdg = (Segment_Delaunay_graph_2&)sdg;
|
||||
sdg2 = sdg;
|
||||
|
||||
assert( sdg.is_valid() );
|
||||
|
|
|
|||
|
|
@ -148,7 +148,17 @@ public:
|
|||
virtual void itemVisibilityChanged(CGAL::Three::Scene_item*) = 0;
|
||||
//! Clears the current selection then sets the selected item to the target index.
|
||||
//! Used to update the selection in the Geometric Objects view.
|
||||
virtual void setSelectedItem(Item_id) = 0;
|
||||
virtual void setSelectedItem(Item_id) = 0;
|
||||
//! \brief ignore data updating.
|
||||
//!
|
||||
//! This will ignore all the individual calls to `itemChanged()` until
|
||||
//! `setUpdatesEnabled()` is called whith `b` being `true`.
|
||||
//!
|
||||
virtual void setUpdatesEnabled(bool b) =0;
|
||||
//!
|
||||
//! \brief Updates all the items in the SceneView.
|
||||
//!
|
||||
virtual void allItemsChanged() = 0;
|
||||
}; // end interface Scene_interface
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ public Q_SLOTS:
|
|||
virtual void setColor(QColor c) { color_ = c;}
|
||||
//!Setter for the RGB color of the item. Calls setColor(QColor).
|
||||
//!@see setColor(QColor c)
|
||||
void setRbgColor(int r, int g, int b) { setColor(QColor(r, g, b)); }
|
||||
void setRgbColor(int r, int g, int b) { setColor(QColor(r, g, b)); }
|
||||
//!Sets the name of the item.
|
||||
virtual void setName(QString n) { name_ = n; }
|
||||
//!Sets the visibility of the item.
|
||||
|
|
@ -339,6 +339,7 @@ public Q_SLOTS:
|
|||
//!This function is called by `Scene::changeGroup` and should not be
|
||||
//!called manually.
|
||||
virtual void moveToGroup(Scene_group_item* group);
|
||||
void setRenderingMode(int m) { setRenderingMode((RenderingMode)m);}
|
||||
//!Sets the rendering mode of the item.
|
||||
//!@see RenderingMode
|
||||
virtual void setRenderingMode(RenderingMode m) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ int main()
|
|||
{ 100, 100, 100, 100, 100, 100, 100 }
|
||||
};
|
||||
|
||||
typedef CGAL::Triangulation<CGAL::Epick_d< CGAL::Dimension_tag<7> > > T;
|
||||
typedef CGAL::Delaunay_triangulation<CGAL::Epick_d< CGAL::Dimension_tag<7> > > T;
|
||||
T dt(7);
|
||||
|
||||
std::vector<T::Point> points;
|
||||
|
|
|
|||
Loading…
Reference in New Issue