/CGAL-4.0.2/demo/Triangulation_3/Viewer.cpp
# · C++ · 1298 lines · 886 code · 151 blank · 261 comment · 297 complexity · 1815f5b15f638176a8aac3c816ce439f MD5 · raw file
- #include "Viewer.h"
- #include <CGAL/glu.h>
- using namespace std;
- #include "Viewer.moc" // .moc will be the output from moc preprocessor
- void Viewer::init()
- {
- /* Initial timer for playing incremental construction */
- m_pTimer = new QTimer(this);
- connect(m_pTimer, SIGNAL(timeout()), this, SLOT(incremental_insert()));
- /* Scene inits */
- setBackgroundColor(::Qt::white);
- // scene are defined by a sphere of 2.0, camera at the center, i.e. (0, 0, 0)
- setSceneCenter( qglviewer::Vec(-0.,-0.,-0.) );
- setSceneRadius( 2. );
- // show text message
- setTextIsEnabled(true);
- setForegroundColor(::Qt::red);
- setFont(QFont("Arial Black", 16, QFont::Bold));
- /* OpenGL inits */
- // Increase the material shininess, so that the difference between
- // the two versions of the spiral is more visible.
- glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
- GLfloat specular_color[4] = { 0.8f, 0.8f, 0.8f, 1.0 };
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular_color);
- // Set Smooth Shading
- ::glShadeModel(GL_SMOOTH);
- // depth buffer setup
- ::glClearDepth(1.0f);
- ::glEnable(GL_DEPTH_TEST);
- ::glDepthFunc(GL_LEQUAL);
- ::glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
- // enable semi-transparent culling planes
- ::glEnable(GL_BLEND);
- ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- // anti-aliasing, i.e. reduce jaggedness (if the OpenGL driver permits that)
- ::glEnable(GL_POINT_SMOOTH);
- ::glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
- ::glEnable(GL_LINE_SMOOTH);
- ::glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
- /* Add mouse and key description */
- setKeyDescription( Qt::CTRL + Qt::Key_G, tr("Generate points") );
- setKeyDescription( Qt::CTRL + Qt::Key_O, tr("Load points") );
- setKeyDescription( Qt::CTRL + Qt::Key_S, tr("Save points") );
- setKeyDescription( Qt::CTRL + Qt::Key_Comma, tr("Preference") );
- setKeyDescription( Qt::CTRL + Qt::Key_H, tr("Hide Kernel Demo") );
- setKeyDescription( Qt::CTRL + Qt::Key_Q, tr("Quit Kernel Demo") );
- setKeyDescription( Qt::Key_Return,
- tr("Insert new point to triangulation in <u>Input-Point</u> mode") );
- setKeyDescription( Qt::Key_Escape,
- tr("Cancel insertion in <u>Input-Point</u> mode;<br>")
- + tr("Cancel current selection in <u>Select</u> mode") );
- setKeyDescription( Qt::Key_Delete, tr("Delete selected vertices in <u>Select</u> mode") );
- setMouseBindingDescription( Qt::LeftButton,
- tr("Hold to move new point in <u>Input-Point</u> mode;<br>")
- + tr("Hold to move a vertex in <u>Move</u> mode") );
- setMouseBindingDescription( Qt::SHIFT + Qt::LeftButton,
- tr("Click to insert a vertex in <u>Input-Vertex</u> mode;<br>")
- + tr("Click to insert a point in <u>Input-Point</u> mode;<br>")
- + tr("Click or Drag to select multiple points in <u>Select</u> mode;<br>")
- + tr("Click to place a query point in <u>Find-Nearest-Neighbor</u> mode;<br>")
- + tr("Click to place a query point in <u>Show-Empty-Sphere</u> mode") );
- setMouseBindingDescription( Qt::CTRL + Qt::LeftButton,
- tr("Drag to add vertices to current selection in <u>Select</u> mode") );
- }
- QString Viewer::helpString() const
- {
- QString text("<h1>3D Triangulation Demo</h1>");
- text += "This example illustrates a generic interactive demo for 3D Triangulation in CGAL. ";
- text += "This demo could be used as a simple skeleton ";
- text += "for potential demos of other 3D packages or for teaching CGAL.<br><br>";
- text += "The key feature is to edit vertices/points with mouse.";
- text += "There are several modes:<br><br>";
- text += " - <u>Normal Mode</u>: ";
- text += "Rotate, zoom, or translate camera using mouse.<br>";
- text += " - <u>Insert Vertex</u>: ";
- text += "Insert a vertex on the surface of the trackball ";
- text += "and the triangulation will be updated correspondingly.<br>";
- text += " - <u>Insert Point</u>: ";
- text += "Insert a point on the surface of the trackball. ";
- text += "Its conflict region will be highlighted. ";
- text += "When the new point is moving, ";
- text += "its conflict region will be updated correspondingly.<br>";
- text += " - <u>Select</u>: ";
- text += "Click or drag mouse left button to select multiple points.<br>";
- text += " - <u>Move</u>: Hold mouse left button to move a vertex ";
- text += "and the triangulation will be updated correspondingly.<br>";
- text += " - <u>Find Nearest Neighbor</u>: ";
- text += "Place a query point and its nearest neighbor will be highlighted.<br>";
- text += " - <u>Show Empty Sphere</u>: ";
- text += "Place a query point, locate the point in a cell ";
- text += "and then show the empty sphere of that cell. ";
- text += "An empty sphere of a cell is a sphere ";
- text += "with all four vertices of the cell lying on it ";
- text += "and no other vertices inside it.<br><br>";
- text += "<b>Shift+Wheel</b> to resize the trackball when it exists. ";
- text += "See <b>Mouse</b> page for more details.<br><br>";
- text += "Other basic features include:<br>";
- text += " - Randomly generate points,<br>";
- text += " - Read/Write files,<br>";
- text += " - Show vertices, Voronoi edges, Delaunay edges, and/or facets,<br>";
- text += " - Incremental Construct: ";
- text += "Re-construct the current triangulation incrementally. ";
- text += "If no triangulation exists yet, randomly generate 100 points ";
- text += "and construct a Delaunay triangulation of those points.<br>";
- return text;
- }
- /*************************************************************/
- /* Draw functions */
- void Viewer::draw()
- {
- if( m_pScene == NULL ) return;
- QFont fontPrompt("Arial", 14);
- if( m_showAxis ) {
- qglColor(::Qt::black);
- drawAxis( sceneRadius() );
- }
- /* Draw vertices */
- if ( m_showVertex && m_pScene->m_dt.number_of_vertices()>0 ) {
- for(QList<Vertex_handle>::iterator vit = m_pScene->m_vhArray.begin();
- vit < m_pScene->m_vhArray.end(); ++vit) {
- if( m_curMode == SELECT && (*vit)->isSeled() ) continue;
- if( (*vit) == m_nearestNb ) continue;
- drawVertex( (*vit)->point(), m_colorVertex, m_fSizeVertex );
- }//end-for-points
- }//end-if-points
- /* Draw all points during incremental mode */
- if( !m_incrementalPts.isEmpty() ) {
- /* draw the rest to-be-inserted vertices */
- for(QList<Point_3>::iterator pit=m_incrementalPts.begin();
- pit < m_incrementalPts.end(); ++pit) {
- drawVertex( (*pit), ::Qt::gray, m_fSizeVertex );
- }
- switch( m_curStep ) {
- case NEWPT:
- /* Show prompt messages */
- qglColor( ::Qt::black );
- drawText( 10, 20, tr("Highlight the next-to-insert point"), fontPrompt );
- /* Highlight the next-to-insert point */
- drawVertex( m_curIncPt, ::Qt::red, m_fSizeVertex );
- break;
- case CELL: // show the tetrahedron that contains the point
- /* Show prompt messages */
- qglColor( ::Qt::black );
- drawText( 10, 20, tr("Show the tetrahedron containing the point"), fontPrompt );
- drawText( 10, 40, tr("(Only finite facets are drawn)"), fontPrompt );
- /* Highlight the next-to-insert vertex */
- drawVertex( m_curIncPt, ::Qt::red, m_fSizeVertex );
- /* Draw the cell containing that point */
- for(int i=0; i<4; ++i) {
- if( m_pScene->m_dt.is_infinite(m_cellContain, i) ) continue;
- drawFacet( m_pScene->m_dt.triangle( m_cellContain, i ), m_colorFacet );
- }//end-for-facets
- break;
- case CONFLICT: // show the conflict region
- /* Show prompt messages */
- qglColor( ::Qt::black );
- drawText( 10, 20, tr("Show the conflict region"), fontPrompt );
- /* Highlight the next-to-insert vertex */
- drawVertex( m_curIncPt, ::Qt::red, m_fSizeVertex );
- /* Draw conflict region */
- for(QList<Facet>::iterator fit = m_boundaryFacets.begin();
- fit < m_boundaryFacets.end(); ++fit) {
- if( m_pScene->m_dt.is_infinite(*fit) ) continue;
- drawFacet( m_pScene->m_dt.triangle(*fit), QColor(215, 80, 0, 96) ); //semi-transparent purple
- }//end-for-facets
- break;
- default:
- break;
- }//end-of=switch
- }//end-if-incpts
- /* Draw Delaunay edges */
- if( m_showDEdge ) {
- for(edges_iterator eit = m_pScene->m_dt.finite_edges_begin();
- eit != m_pScene->m_dt.finite_edges_end(); ++eit) {
- Segment_3 seg = m_pScene->m_dt.segment(*eit);
- drawEdge( seg.vertex(0), seg.vertex(1), m_colorDEdge, m_fSizeDEdge );
- }//end-for-edges
- }//end-if-dt
- /* Draw Voronoi edges */
- if( m_showVEdge ) {
- for(facets_iterator fit = m_pScene->m_dt.finite_facets_begin();
- fit != m_pScene->m_dt.finite_facets_end(); ++fit) {
- Object_3 o = m_pScene->m_dt.dual(*fit);
- if (const Segment_3 *s = CGAL::object_cast<Segment_3>(&o)) {
- drawEdge( s->vertex(0), s->vertex(1), m_colorVEdge, m_fSizeVEdge );
- } else if (const Ray_3 *r = CGAL::object_cast<Ray_3>(&o)) {
- drawEdge( r->point(0), // the source of the ray
- r->point(1), // another point on the ray, different from the source
- m_colorVEdge, m_fSizeVEdge );
- }
- }//end-for-edges
- }//end-if-vd
- /* Draw facets */
- if( m_showFacet ) {
- for(facets_iterator fit = m_pScene->m_dt.finite_facets_begin();
- fit != m_pScene->m_dt.finite_facets_end(); ++fit) {
- drawFacet( m_pScene->m_dt.triangle(*fit), m_colorFacet );
- }//end-for-facets
- }//end-if-facets
- /* Insert vertex mode */
- if( m_curMode == INSERT_V ) {
- /* Show prompt messages */
- qglColor( ::Qt::black );
- drawText( width()-200, 20, tr("Shift+Left: Insert a vertex"), fontPrompt );
- drawText( width()-200, 40, tr("Shift+Wheel: Resize trackball"), fontPrompt );
- /* Draw the trackball */
- drawSphere( m_fRadius, m_colorTrackball );
- }//end-if-insv
- /* Insert point mode */
- else if( m_curMode == INSERT_PT ) {
- /* Show prompt messages */
- qglColor( ::Qt::black );
- drawText( width()-200, 20, tr("Shift+Left: Insert a point"), fontPrompt );
- drawText( width()-200, 40, tr("Hold Left: Move the point"), fontPrompt );
- drawText( width()-200, 60, tr("Return: Insert to DT"), fontPrompt );
- drawText( width()-200, 80, tr("Escape: Cancel insertion"), fontPrompt );
- drawText( width()-200, 100, tr("Shift+Wheel: Resize trackball"), fontPrompt );
- /* Draw the trackball */
- drawSphere( m_fRadius, m_colorTrackball );
- if( m_hasNewPt ) {
- /* Draw the newly inserted point */
- drawVertex( m_newPt, ::Qt::red, m_fSizeVertex );
- /* Draw conflict region */
- for(QList<Facet>::iterator fit = m_boundaryFacets.begin();
- fit < m_boundaryFacets.end(); ++fit) {
- if( m_pScene->m_dt.is_infinite(*fit) ) continue;
- drawFacet( m_pScene->m_dt.triangle(*fit), QColor(215, 80, 0, 96) ); //semi-transparent purple
- }//end-for-facets
- }//end-if-shown
- }//end-if-inspt
- /* Select mode */
- else if( m_curMode == SELECT) {
- /* Show prompt messages */
- qglColor( ::Qt::black );
- drawText( width()-200, 20, tr("Shift+Left: Select"), fontPrompt );
- drawText( width()-200, 40, tr("Ctrl+Left: Add selection"),
- QFont("Arial", 14) );
- drawText( width()-200, 60, tr("Escape: Cancel selection"), fontPrompt );
- drawText( width()-200, 80, tr("DEL: Delete selected"), fontPrompt );
- /* Highlight the selected vertices */
- for(QList<int>::iterator vit=m_vidSeled.begin(); vit<m_vidSeled.end(); ++vit) {
- drawVertex( m_pScene->m_vhArray.at(*vit)->point(), ::Qt::red, m_fSizeVertex );
- }//end-for-seledpts
- /* Draw the multiple selection window */
- if( m_isPress ) {
- ::glDisable( GL_LIGHTING );
- startScreenCoordinatesSystem();
- qglColor( QColor(80, 180, 180, 64) );
- ::glBegin(GL_QUADS);
- ::glVertex2i(m_rectSel.left(), m_rectSel.top());
- ::glVertex2i(m_rectSel.right(), m_rectSel.top());
- ::glVertex2i(m_rectSel.right(), m_rectSel.bottom());
- ::glVertex2i(m_rectSel.left(), m_rectSel.bottom());
- ::glEnd();
- stopScreenCoordinatesSystem();
- ::glEnable( GL_LIGHTING );
- }//end-if-press
- }//end-if-sel
- /* Move mode */
- else if( m_curMode == MOVE ) {
- /* Show prompt messages */
- qglColor( ::Qt::black );
- drawText( width()-200, 20, tr("Left Click: Select"), fontPrompt );
- if( m_isMoving ) {
- drawText( width()-200, 40, tr("Shift+Wheel: Resize trackball"), fontPrompt );
- /* Draw the trackball */
- drawSphere( m_fRadius, m_colorTrackball );
- /* Highlight the moving point */
- drawVertex( m_pScene->m_vhArray.at( m_vidMoving )->point(), ::Qt::red, m_fSizeVertex );
- }//end-if-v
- }//end-if-move
- /* FindNb mode */
- else if( m_curMode == FINDNB ) {
- /* Show prompt messages */
- qglColor( ::Qt::black );
- drawText( width()-200, 20, tr("Shift+Left: Place query point"), fontPrompt );
- drawText( width()-200, 40, tr("Shift+Wheel: Resize trackball"), fontPrompt );
- /* Draw the trackball */
- drawSphere( m_fRadius, m_colorTrackball );
- /* Draw the nearest neighbor */
- if( m_nearestNb != NULL ) {
- drawVertex( m_queryPt, ::Qt::red, m_fSizeVertex );
- drawVertex( m_nearestNb->point(), ::Qt::red, m_fSizeVertex );
- }
- }//end-if-findnb
- /* EmptySphere mode */
- else if( m_curMode == EMPTYSPH ) {
- /* Show prompt messages */
- qglColor( ::Qt::black );
- drawText( width()-200, 20, tr("Shift+Left: Place query point"), fontPrompt );
- drawText( width()-200, 40, tr("Press S: Show/Hide trackball"), fontPrompt );
- drawText( width()-200, 60, tr("Shift+Wheel: Resize trackball"), fontPrompt );
- /* Draw the trackball */
- if( m_showTrackball )
- drawSphere( m_fRadius, m_colorTrackball );
- if( m_hasEmptyS ) {
- /* Draw the query point */
- drawVertex( m_queryPt, ::Qt::red, m_fSizeVertex );
- /* Draw the cell containing that point */
- for(int i=0; i<4; ++i) {
- if( m_pScene->m_dt.is_infinite(m_cellContain, i) ) continue;
- drawFacet( m_pScene->m_dt.triangle( m_cellContain, i ), m_colorFacet );
- }//end-for-facets
- /* Draw the sphere */
- drawSphere( m_fREmptyS, m_colorEmptySphere, m_centerPt );
- }
- }//end-if-emptyS
- }
- void Viewer::drawVertex(const Point_3& p, const QColor& clr, float r)
- {
- /* Draw regular points */
- if( m_isFlat ) {
- // disable lighting
- ::glDisable( GL_LIGHTING );
- ::glPointSize(8.0);
- qglColor( clr );
- ::glBegin(GL_POINTS);
- ::glVertex3f( p.x(), p.y(), p.z() );
- ::glEnd();
- // resume lighting
- ::glEnable( GL_LIGHTING );
- return;
- }
- /* Draw vertices as 3D balls */
- GLboolean lighting, colorMaterial;
- ::glGetBooleanv( GL_LIGHTING, &lighting );
- ::glGetBooleanv( GL_COLOR_MATERIAL, &colorMaterial );
- ::glEnable( GL_LIGHTING );
- ::glDisable(GL_COLOR_MATERIAL);
- float color[4];
- color[0] = clr.redF();
- color[1] = clr.greenF();
- color[2] = clr.blueF();
- color[3] = clr.alphaF();
- // move to the point
- ::glPushMatrix();
- ::glTranslatef( p.x(), p.y(), p.z() );
- // draw
- GLUquadricObj* quadratic = ::gluNewQuadric(); // Create A Pointer To The Quadric Object
- ::gluQuadricNormals( quadratic, GLU_SMOOTH ); // Create Smooth Normals
- ::glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color );
- ::gluSphere( quadratic, r, 16, 16 );
- // move back to origin
- ::glPopMatrix();
- if ( colorMaterial )
- ::glEnable( GL_COLOR_MATERIAL );
- if ( !lighting )
- ::glDisable( GL_LIGHTING );
- }
- void Viewer::drawEdge(const Point_3& from, const Point_3& to, const QColor& clr, float r)
- {
- /* Draw regular lines */
- if( m_isFlat ) {
- // disable lighting
- ::glDisable( GL_LIGHTING );
- ::glLineWidth(1.0);
- qglColor( clr );
- ::glBegin(GL_LINES);
- ::glVertex3f( from.x(), from.y(), from.z() );
- ::glVertex3f( to.x(), to.y(), to.z() );
- ::glEnd();
- // resume lighting
- ::glEnable( GL_LIGHTING );
- return;
- }
- /* Draw edges as 3D cylinders */
- GLboolean lighting, colorMaterial;
- ::glGetBooleanv( GL_LIGHTING, &lighting );
- ::glGetBooleanv( GL_COLOR_MATERIAL, &colorMaterial );
- ::glEnable( GL_LIGHTING );
- ::glDisable(GL_COLOR_MATERIAL);
- float color[4];
- color[0] = clr.redF();
- color[1] = clr.greenF();
- color[2] = clr.blueF();
- color[3] = clr.alphaF();
- Vector_3 v = to - from;
- // compute the length of the edge
- // method 1:
- // float length = sqrt( CGAL::squared_distance( from, to ) );
- // method 2:
- float length = sqrt( v.squared_length() );
- // normalize
- v = v / length;
- // compute the angle: cos theta = v.z/1.0
- GLfloat angle = acos( v.z() ) / 3.1415927 * 180;
- ::glPushMatrix();
- // move to "from" point
- ::glTranslatef( from.x(), from.y(), from.z() );
- // rotate from z-axis to from-->to
- // axis: cross product of z-axis and from-->to
- ::glRotatef( angle, -v.y(), v.x(), 0.0f );
- // draw
- GLUquadricObj* quadratic = ::gluNewQuadric(); // Create A Pointer To The Quadric Object
- ::gluQuadricNormals( quadratic, GLU_SMOOTH ); // Create Smooth Normals
- ::glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color );
- // gluCylinder draws a cylinder oriented along the z-axis
- ::gluCylinder( quadratic, r, r, length, 16, 4 );
- // move back to origin
- ::glPopMatrix();
- if ( colorMaterial )
- ::glEnable( GL_COLOR_MATERIAL );
- if ( !lighting )
- ::glDisable( GL_LIGHTING );
- }
- void Viewer::drawFacet(const Triangle_3& t, const QColor& /*clr*/)
- {
- // disable lighting
- ::glDisable( GL_LIGHTING );
- // disable depth buffer writing
- ::glDepthMask( GL_FALSE );
- qglColor( m_colorFacet );
- ::glBegin(GL_TRIANGLES);
- Point_3 p0 = t.vertex(0);
- Point_3 p1 = t.vertex(1);
- Point_3 p2 = t.vertex(2);
- ::glVertex3f( p0.x(), p0.y(), p0.z() );
- ::glVertex3f( p1.x(), p1.y(), p1.z() );
- ::glVertex3f( p2.x(), p2.y(), p2.z() );
- ::glEnd();
- // resume depth buffer writing
- ::glDepthMask( GL_TRUE );
- // resume lighting
- ::glEnable( GL_LIGHTING );
- }
- void Viewer::drawSphere(float r, const QColor& clr, const Point_3& center)
- {
- GLboolean lighting, colorMaterial;
- ::glGetBooleanv( GL_LIGHTING, &lighting );
- ::glGetBooleanv( GL_COLOR_MATERIAL, &colorMaterial );
- ::glEnable( GL_LIGHTING );
- ::glDisable(GL_COLOR_MATERIAL);
- float color[4];
- color[0] = clr.redF();
- color[1] = clr.greenF();
- color[2] = clr.blueF();
- color[3] = clr.alphaF();
- ::glPushMatrix();
- // move to the point
- if( center != CGAL::ORIGIN ) ::glTranslatef( center.x(), center.y(), center.z() );
- // disable depth buffer writing
- ::glDepthMask( GL_FALSE );
- // draw
- GLUquadricObj* quadratic = ::gluNewQuadric(); // Create A Pointer To The Quadric Object
- ::gluQuadricNormals( quadratic, GLU_SMOOTH ); // Create Smooth Normals
- ::glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color );
- ::gluSphere( quadratic, r, 32, 32 );
- // resume depth buffer writing
- ::glDepthMask( GL_TRUE );
- // move back to origin
- ::glPopMatrix();
- if ( colorMaterial )
- ::glEnable( GL_COLOR_MATERIAL );
- if ( !lighting )
- ::glDisable( GL_LIGHTING );
- }
- /*************************************************************/
- /* Select functions */
- void Viewer::drawWithNames()
- {
- for(int i=0; i<m_pScene->m_vhArray.size(); ++i) {
- // push a name for each point onto the name stack
- // note: it can NOT be used between glBegin and glEnd
- ::glPushName( i );
- // draw the point
- ::glBegin(GL_POINTS);
- Point_3& p = m_pScene->m_vhArray.at(i)->point();
- ::glVertex3f(p.x(), p.y(), p.z());
- ::glEnd();
- // pop one name off the top of the name stack
- ::glPopName();
- }//end-for-points
- // push a name for the newly inserted point
- if( m_curMode == INSERT_PT && m_hasNewPt ) {
- ::glPushName( ::GLuint(-1) );
- ::glBegin(GL_POINTS);
- ::glVertex3f(m_newPt.x(), m_newPt.y(), m_newPt.z());
- ::glEnd();
- ::glPopName();
- }//end-if-newPt
- }
- void Viewer::endSelection(const QPoint& /*point*/)
- {
- // flush GL buffers
- ::glFlush();
- // reset GL_RENDER mode (was GL_SELECT) and get the number of selected points
- size_t nSel = ::glRenderMode(GL_RENDER);
- /* No selection */
- if( nSel <= 0 ) {
- if( m_curMode == SELECT )
- m_isPress = false;
- }//end-if-notselected
- // each hit record has 4 data: # of names in name stack, min and max depth of old hits,
- // name stack contents [see glSelectBuffer man page for more details]
- // i.e. (selectBuffer())[4*i+3] is the id pushed on the stack
- /* Check whether the new point is clicked on */
- else if( m_curMode == INSERT_PT ) {
- if( m_hasNewPt && (selectBuffer())[3] == ::GLuint(-1) )
- m_isMoving = true;
- }//end-if-inspt
- /* Check whether vertex is clicked on */
- else if( m_curMode == MOVE ) {
- m_isMoving = true;
- m_vidMoving = (selectBuffer())[3];
- // compute the corresponding size of trackball, i.e. selectedV is on the ball
- Point_3 p = m_pScene->m_vhArray.at( m_vidMoving )->point();
- m_fRadius = sqrt( p.x()*p.x() + p.y()*p.y() + p.z()*p.z() );
- }//end-if-move
- /* Store current selections */
- else { // m_curMode == SELECT
- if( m_selMode == NORMAL ) {
- // remove the old selections
- for(QList<int>::iterator vit=m_vidSeled.begin();
- vit < m_vidSeled.end(); ++vit) {
- m_pScene->m_vhArray.at(*vit)->setSeled( false );
- }
- m_vidSeled.clear();
- // record the new selections
- for(std::size_t i=0; i<nSel; ++i) {
- m_vidSeled.push_back( (selectBuffer())[4*i+3] );
- m_pScene->m_vhArray.at( m_vidSeled.back() )->setSeled();
- }
- } else {
- for(std::size_t i=0; i<nSel; ++i) {
- if( !m_vidSeled.contains( (selectBuffer())[4*i+3] ) ) {
- m_vidSeled.push_back( (selectBuffer())[4*i+3] );
- m_pScene->m_vhArray.at( (selectBuffer())[4*i+3] )->setSeled();
- }//end-if-contain
- }//end-for
- }//end-if-add
- }//end-if-sel
- }
- /*************************************************************/
- /* Mouse and Keyboard functions */
- void Viewer::mousePressEvent(QMouseEvent *event)
- {
- // button() holds the button that caused the event
- // note: for mouse move event, button() always return Qt::NoButton
- // modifiers() holds the keyboard modifier flags at the time of the event
- // buttons() holds the button state when the event was generated,
- // i.e. all buttons that are pressed down
- // pos() holds the mouse cursor's position relative to the receiving widget
- // Get event modifiers key
- #if QT_VERSION < 0x040000
- // Bug in Qt : use 0x0f00 instead of Qt::KeyButtonMask with Qt versions < 3.1
- const Qt::ButtonState modifiers = (Qt::ButtonState)(event->state() & Qt::KeyButtonMask);
- #else
- const Qt::KeyboardModifiers modifiers = event->modifiers();
- #endif
- if( m_curMode == INSERT_V
- && event->button() == Qt::LeftButton && modifiers == Qt::SHIFT ) {
- m_isPress = true;
- }//end-if-insv
- else if(m_curMode == INSERT_PT && event->button() == Qt::LeftButton ) {
- /* shift+left to insert */
- if( modifiers == Qt::SHIFT ) {
- if( m_pScene->m_dt.is_valid() && m_pScene->m_dt.dimension() == 3 )
- m_isPress = true;
- else
- displayMessage( tr("There exists no triangulation yet.") );
- m_hasNewPt = false;
- } else { /* left button to move */
- m_isMoving = false;
- // define selection window (default was 3)
- setSelectRegionWidth( 10 );
- setSelectRegionHeight( 10 );
- // perform the selection
- select( event->pos() );
- if( m_isMoving )
- // redraw window
- updateGL();
- else
- // if no point is selected, then regular action (rotation) will be performed
- QGLViewer::mousePressEvent(event);
- }//end-if-shift
- }//end-if-inspt
- else if( m_curMode == SELECT && event->button() == Qt::LeftButton ) {
- // set the selection mode
- switch( modifiers ) {
- case Qt::SHIFT : // select
- m_isPress = true;
- m_selMode = NORMAL;
- // initialize multiple selection window
- m_rectSel = QRect( event->pos(), event->pos() );
- // redraw window
- updateGL();
- break;
- case Qt::CTRL : // add selection
- m_isPress = true;
- m_selMode = ADD;
- // initialize multiple selection window
- m_rectSel = QRect( event->pos(), event->pos() );
- // redraw window
- updateGL();
- break;
- default: // rotate
- QGLViewer::mousePressEvent(event);
- break;
- }
- }//end-if-select
- else if(m_curMode == MOVE && event->button() == Qt::LeftButton ) {
- m_isMoving = false;
- // define selection window (default was 3)
- setSelectRegionWidth( 10 );
- setSelectRegionHeight( 10 );
- // perform the selection
- select( event->pos() );
- if( m_isMoving ) // redraw window
- updateGL();
- else // if no point is selected, then regular action (rotation) will be performed
- QGLViewer::mousePressEvent(event);
- }//end-if-move
- else if( m_curMode == FINDNB
- && event->button() == Qt::LeftButton && modifiers == Qt::SHIFT ) {
- if( m_pScene->m_dt.is_valid() && m_pScene->m_dt.dimension() == 3 )
- m_isPress = true;
- else
- displayMessage( tr("There exists no triangulation yet.") );
- }//end-if-findnb
- else if( m_curMode == EMPTYSPH
- && event->button() == Qt::LeftButton && modifiers == Qt::SHIFT ) {
- if( m_pScene->m_dt.is_valid() && m_pScene->m_dt.dimension() == 3 )
- m_isPress = true;
- else
- displayMessage( tr("There exists no triangulation yet.") );
- m_hasEmptyS = false;
- }//end-if-emptyS
- else
- QGLViewer::mousePressEvent(event);
- }
- void Viewer::mouseMoveEvent(QMouseEvent *event)
- {
- if( m_curMode == INSERT_PT && m_isMoving ) {
- Vec pt;
- if( computeIntersect( event->pos(), pt ) ) {
- m_newPt = Point_3(pt.x, pt.y, pt.z);
- // compute the conflict hole induced by point p
- computeConflict( m_newPt );
- }//end-if-compute
- // redraw
- updateGL();
- }//end-if-inspt
- else if( m_curMode == SELECT && m_isPress ) {
- // update multiple selection window
- m_rectSel.setBottomRight( event->pos() );
- // redraw
- updateGL();
- }//end-if-sel
- else if( m_curMode == MOVE && m_isMoving ) {
- Vec pt;
- if( computeIntersect( event->pos(), pt ) ) {
- // note: QList::operator[] return a modifiable reference;
- // while QList::at return a const reference
- #if CGAL_VERSION_NR < 1030700000
- // move_point moves the point stored in v to p while preserving the Delaunay property
- // it calls remove(v) followed by insert(p) and return the new handle
- // it supposely faster when the point has not moved much
- m_pScene->m_vhArray[m_vidMoving] = m_pScene->m_dt.move_if_no_collision(
- m_pScene->m_vhArray.at( m_vidMoving ),
- Point_3( pt.x, pt.y, pt.z ) );
- #else
- // move_if_no_collision moves the point stored in v to pt
- // if there is not already another vertex placed on pt,
- // the triangulation is modified s.t. the new position of v is pt;
- // otherwise, the vertex at point pt is returned.
- Vertex_handle vh = m_pScene->m_dt.move_if_no_collision(
- m_pScene->m_vhArray.at( m_vidMoving ),
- Point_3( pt.x, pt.y, pt.z ) );
- int id1 = m_pScene->m_vhArray.indexOf( vh );
- int id2 = m_pScene->m_vhArray.indexOf( vh, m_vidMoving+1 );
- // remove the duplicate in vhArray
- if( id1 != m_vidMoving )
- m_pScene->m_vhArray.removeAt( id1 );
- else if( id2 != -1 )
- m_pScene->m_vhArray.removeAt( id2 );
- m_pScene->m_vhArray[m_vidMoving] = vh;
- #endif
- }//end-if-compute
- // redraw
- updateGL();
- }//end-if-move
- else
- QGLViewer::mouseMoveEvent(event);
- }
- void Viewer::mouseReleaseEvent(QMouseEvent *event)
- {
- /* INS_V mode - Shift+Left: compute and insert a vertex */
- if( m_curMode == INSERT_V && m_isPress ) {
- m_isPress = false;
- Vec pt;
- if( computeIntersect( event->pos(), pt ) ) {
- m_pScene->m_vhArray.push_back( m_pScene->m_dt.insert( Point_3( pt.x, pt.y, pt.z ) ) );
- }//end-if-compute
- // redraw
- updateGL();
- }//end-if-ins
- /* INS_PT mode - Shift+Left: compute and insert a point */
- else if( m_curMode == INSERT_PT && m_isPress ) {
- m_isPress = false;
- Vec pt;
- if( computeIntersect( event->pos(), pt ) ) {
- m_hasNewPt = true;
- m_newPt = Point_3(pt.x, pt.y, pt.z);
- // compute the conflict hole induced by point p
- computeConflict( m_newPt );
- }//end-if-compute
- // redraw
- updateGL();
- }//end-if-inspt
- /* INS_PT mode - Left: compute and insert a point */
- else if( m_curMode == INSERT_PT && m_isMoving ) {
- m_isMoving = false;
- Vec pt;
- if( computeIntersect( event->pos(), pt ) ) {
- m_newPt = Point_3(pt.x, pt.y, pt.z);
- // compute the conflict hole induced by point p
- computeConflict( m_newPt );
- }//end-if-compute
- // redraw
- updateGL();
- }//end-if-inspt
- /* SEL mode - Left: terminate multiple point selection */
- else if( m_curMode == SELECT && m_isPress ) {
- // might swap left/right and top/bottom to make rectanle valid
- #if QT_VERSION < 0x040000
- m_rectSel = m_rectSel.normalize();
- #else
- m_rectSel = m_rectSel.normalized();
- #endif
- if( m_rectSel.width() == 1 && m_rectSel.height() == 1 ) { /* select a point */
- // set a default selection window
- setSelectRegionWidth( 10 );
- setSelectRegionHeight( 10 );
- // compute rectangle center and perform selection
- select( m_rectSel.center() );
- if( m_isPress ) {
- m_isPress = false;
- } else {
- displayMessage( tr("No point is selected.") );
- }
- } else { /* select multiple points, ie. selection window > 1 */
- // define selection window
- if( m_rectSel.width() < 10 )
- setSelectRegionWidth( 10 );
- else
- setSelectRegionWidth( m_rectSel.width() );
- if( m_rectSel.height() < 10 )
- setSelectRegionHeight( 10 );
- else
- setSelectRegionHeight( m_rectSel.height() );
- // compute rectangle center and perform selection
- select( m_rectSel.center() );
- if( m_isPress ) {
- m_isPress = false;
- displayMessage( QString::number(m_vidSeled.size()) + tr(" points are selected") );
- } else { // empty window will cancel the current selection
- for(QList<int>::iterator iit = m_vidSeled.begin(); iit < m_vidSeled.end(); ++iit)
- m_pScene->m_vhArray.at(*iit)->setSeled( false );
- m_vidSeled.clear();
- }
- }//end-if-selwindow
- // update display to show
- updateGL();
- }//end-if-select
- /* MOVE mode - Left: terminate point moving */
- else if( m_curMode == MOVE && m_isMoving ) {
- Vec pt;
- if( computeIntersect( event->pos(), pt ) ) {
- // note: QList::operator[] return a modifiable reference;
- // while QList::at return a const reference
- #if CGAL_VERSION_NR < 1030700000
- // move_point moves the point stored in v to p while preserving the Delaunay property
- // it calls remove(v) followed by insert(p) and return the new handle
- // it supposely faster when the point has not moved much
- m_pScene->m_vhArray[m_vidMoving] = m_pScene->m_dt.move_if_no_collision(
- m_pScene->m_vhArray.at( m_vidMoving ),
- Point_3( pt.x, pt.y, pt.z ) );
- #else
- // move_if_no_collision moves the point stored in v to pt
- // if there is not already another vertex placed on pt,
- // the triangulation is modified s.t. the new position of v is pt;
- // otherwise, the vertex at point pt is returned.
- Vertex_handle vh = m_pScene->m_dt.move_if_no_collision(
- m_pScene->m_vhArray.at( m_vidMoving ),
- Point_3( pt.x, pt.y, pt.z ) );
- int id1 = m_pScene->m_vhArray.indexOf( vh );
- int id2 = m_pScene->m_vhArray.indexOf( vh, m_vidMoving+1 );
- // remove the duplicate in vhArray
- if( id1 != m_vidMoving )
- m_pScene->m_vhArray.removeAt( id1 );
- else if( id2 != -1 )
- m_pScene->m_vhArray.removeAt( id2 );
- m_pScene->m_vhArray[m_vidMoving] = vh;
- #endif
- }//end-if-compute
- // redraw
- updateGL();
- }//end-if-move
- /* FindNb mode - Shift+Left: find the nearest neighbor of the point */
- else if( m_curMode == FINDNB && m_isPress ) {
- m_isPress = false;
- Vec pt;
- if( computeIntersect( event->pos(), pt ) ) {
- m_queryPt = Point_3( pt.x, pt.y, pt.z );
- m_nearestNb = m_pScene->m_dt.nearest_vertex( m_queryPt );
- }//end-if-compute
- // redraw
- updateGL();
- }//end-if-findnb
- /* EmptySphere mode - Shift+Left: show the empty sphere of the cell */
- else if( m_curMode == EMPTYSPH && m_isPress ) {
- m_isPress = false;
- Vec pt;
- m_hasEmptyS = computeIntersect( event->pos(), pt );
- if( m_hasEmptyS ) {
- m_queryPt = Point_3( pt.x, pt.y, pt.z );
- // find the cell that contains point p in its interior
- m_cellContain = m_pScene->m_dt.locate( m_queryPt );
- // show error if point is outside the convex hull
- if( m_pScene->m_dt.is_infinite( m_cellContain ) ) {
- m_hasEmptyS = false;
- displayMessage( tr("Query point is outside the convex hull!") );
- } else { /* compute the empty sphere */
- // find the circumcenter of the four vertices of c
- m_centerPt = m_pScene->m_dt.dual( m_cellContain );
- // compute the radius of the empty sphere
- m_fREmptyS = sqrt( CGAL::squared_distance( m_centerPt,
- m_cellContain->vertex(0)->point() ) );
- }
- }//end-if-compute
- // redraw
- updateGL();
- }//end-if-emptysphere
- else
- QGLViewer::mouseReleaseEvent(event);
- }
- void Viewer::wheelEvent(QWheelEvent *event)
- {
- // Get event modifiers key
- #if QT_VERSION < 0x040000
- // Bug in Qt : use 0x0f00 instead of Qt::KeyButtonMask with Qt versions < 3.1
- const Qt::ButtonState modifiers = (Qt::ButtonState)(event->state() & Qt::KeyButtonMask);
- #else
- const Qt::KeyboardModifiers modifiers = event->modifiers();
- #endif
- if( (m_curMode == INSERT_V || m_curMode == FINDNB || m_curMode == EMPTYSPH )
- && modifiers == Qt::SHIFT ) {
- // delta() returns the distance that the wheel is rotated, in eighths of a degree.
- // note: most mouse types work in steps of 15 degrees
- // positive value: rotate forwards away from the user;
- // negative value: rotate backwards toward the user.
- m_fRadius += (event->delta()*1. / m_iStep ); // inc-/decrease by 0.1 per step
- if( m_fRadius < 0.1 )
- m_fRadius = 0.1;
- // redraw
- updateGL();
- }//end-if-insv
- else if( m_curMode == INSERT_PT && modifiers == Qt::SHIFT ) {
- // delta() returns the distance that the wheel is rotated, in eighths of a degree.
- // note: most mouse types work in steps of 15 degrees
- // positive value: rotate forwards away from the user;
- // negative value: rotate backwards toward the user.
- float origR = m_fRadius;
- m_fRadius += (event->delta()*1. / m_iStep ); // inc-/decrease by 0.1 per step
- if( m_fRadius < 0.1 )
- m_fRadius = 0.1;
- // update the new point and its conflict region
- if( m_hasNewPt ) {
- origR = m_fRadius / origR;
- m_newPt = Point_3( m_newPt.x()*origR, m_newPt.y()*origR, m_newPt.z()*origR );
- // compute the conflict hole induced by point p
- computeConflict( m_newPt );
- }//end-if-conflict
- // redraw
- updateGL();
- }//end-if-inspt
- // resize the trackball when moving a point
- else if( m_curMode == MOVE && modifiers == Qt::SHIFT && m_isMoving ) {
- float origR = m_fRadius;
- m_fRadius += (event->delta()*1. / m_iStep ); // inc-/decrease by 0.1 per step
- if( m_fRadius < 0.1 )
- m_fRadius = 0.1;
- origR = m_fRadius / origR;
- Point_3 pt = m_pScene->m_vhArray.at( m_vidMoving )->point();
- // note: QList::operator[] return a modifiable reference;
- // while QList::at return a const reference
- #if CGAL_VERSION_NR < 1030700000
- // move_point moves the point stored in v to p while preserving the Delaunay property
- // it calls remove(v) followed by insert(p) and return the new handle
- // it supposely faster when the point has not moved much
- m_pScene->m_vhArray[m_vidMoving] = m_pScene->m_dt.move_if_no_collision(
- m_pScene->m_vhArray.at( m_vidMoving ),
- Point_3( pt.x()*origR, pt.y()*origR, pt.z()*origR ) );
- #else
- // move_if_no_collision moves the point stored in v to pt
- // if there is not already another vertex placed on pt,
- // the triangulation is modified s.t. the new position of v is pt;
- // otherwise, the vertex at point pt is returned.
- Vertex_handle vh = m_pScene->m_dt.move_if_no_collision(
- m_pScene->m_vhArray.at( m_vidMoving ),
- Point_3( pt.x()*origR, pt.y()*origR, pt.z()*origR ) );
- int id1 = m_pScene->m_vhArray.indexOf( vh );
- int id2 = m_pScene->m_vhArray.indexOf( vh, m_vidMoving+1 );
- // remove the duplicate in vhArray
- if( id1 != m_vidMoving )
- m_pScene->m_vhArray.removeAt( id1 );
- else if( id2 != -1 )
- m_pScene->m_vhArray.removeAt( id2 );
- m_pScene->m_vhArray[m_vidMoving] = vh;
- #endif
- // redraw
- updateGL();
- }//end-if-move
- else
- QGLViewer::wheelEvent(event);
- }
- void Viewer::keyPressEvent(QKeyEvent *event)
- {
- // Get event modifiers key
- #if QT_VERSION < 0x040000
- // Bug in Qt : use 0x0f00 instead of Qt::KeyButtonMask with Qt versions < 3.1
- const Qt::ButtonState modifiers = (Qt::ButtonState)(event->state() & Qt::KeyButtonMask);
- #else
- const Qt::KeyboardModifiers modifiers = event->modifiers();
- #endif
- /* Insert the newly inserted point as a vertex */
- if( m_curMode == INSERT_PT && m_hasNewPt
- && ( event->key()==Qt::Key_Return || event->key()==Qt::Key_Enter )
- && modifiers==Qt::NoButton ) {
- Facet& f = m_boundaryFacets.first(); // a boundary facet, i.e. a pair (cell_handle, i)
- // insert_in_hole will create a new vertex by starring a hole
- // i.e. delete all conflict cells, create a new vertex,
- // and for each boundary facet, create a new cell with the new vertex
- // it takes in an iterator range of conflict cells which specifies a hole
- // and (begin, i) is a boundary facet that begin is one of the conflict cell
- // but begin->neighbor(i) is not
- // it returns the handle of the new vertex
- m_pScene->m_vhArray.push_back( m_pScene->m_dt.insert_in_hole( m_newPt, // the point
- m_conflictCells.begin(), // cell_begin
- m_conflictCells.end(), // cell_end
- f.first, // cell_handle begin
- f.second ) ); // integer i
- m_hasNewPt = false;
- // erase old conflict hole info
- m_boundaryFacets.clear();
- m_conflictCells.clear();
- // redraw
- updateGL();
- }//end-if-insVertex
- /* Cancel the newly inserted point and its conflict region */
- else if( m_curMode == INSERT_PT && m_hasNewPt
- && event->key()==Qt::Key_Escape && modifiers==Qt::NoButton ) {
- m_hasNewPt = false;
- // erase old conflict hole info
- m_boundaryFacets.clear();
- m_conflictCells.clear();
- // redraw
- updateGL();
- }//end-if-escapeIns
- /* Delete selected points */
- else if( m_curMode == SELECT
- && event->key()==Qt::Key_Delete && modifiers==Qt::NoButton ) {
- // sort selected id's in descending order
- qSort(m_vidSeled.begin(), m_vidSeled.end(), qGreater<int>());
- for(QList<int>::iterator vit=m_vidSeled.begin(); vit<m_vidSeled.end(); ++vit) {
- // remove the selected point from DT and vertex_handle_array
- // note: QList::takeAt will removes the item at index position i and returns it.
- m_pScene->m_dt.remove( m_pScene->m_vhArray.takeAt( *vit ) );
- }
- // clear the selection buffer
- m_vidSeled.clear();
- // redraw
- updateGL();
- }//end-if-del
- /* Cancel the selection */
- else if( m_curMode == SELECT
- && event->key()==Qt::Key_Escape && modifiers==Qt::NoButton ) {
- // clear the selection buffer
- for(QList<int>::iterator iit=m_vidSeled.begin(); iit<m_vidSeled.end(); ++iit) {
- m_pScene->m_vhArray.at(*iit)->setSeled( false );
- }
- m_vidSeled.clear();
- // redraw
- updateGL();
- }//end-if-escapeSel
- /* Show/hide the trackball when drawing the empty sphere */
- else if( m_curMode == EMPTYSPH
- && event->key()==Qt::Key_S && modifiers==Qt::NoButton ) {
- m_showTrackball = !m_showTrackball;
- // redraw
- updateGL();
- }//end-if-showBall
- else
- QGLViewer::keyPressEvent(event);
- }
- /*************************************************************/
- /* Computation functions */
- bool Viewer::computeIntersect( const QPoint & pos, Vec & pt )
- {
- Vec eye, dir;
- // Compute eye position and direction to the clicked point,
- // used to draw a representation of the intersecting line
- camera()->convertClickToLine( pos, eye, dir );
- // Compute the intersection point with the sphere
- // note that the center of the sphere is at the origin (0, 0, 0)
- // thus, (1) pt = eye + t*dir and (2) dist( pt, origin ) = radius
- // i.e. (x_eye + t*x_dir)^2 + (y_eye + t*y_dir)^2 + (z_eye + t*z_dir)^2 = r^2
- // --> t^2( dir*dir ) + 2t( eye*dir ) + eye*eye - r^2 = 0
- // where "dir*dir" is the dot product of vector dir
- // we need to solve t and the smaller t (nearer to eye position) is what we want
- float a = dir*dir;
- float b = eye*dir;
- float c = eye*eye - m_fRadius*m_fRadius;
- float delta = b*b - a*c;
- if( delta < 0 ) {
- displayMessage( tr("Point is not on the sphere!") );
- return false;
- } else {
- float t = ( (-1.)*b - sqrt(delta) ) / a;
- pt = eye + t*dir;
- return true;
- }
- }
- void Viewer::computeConflict( Point_3 pt )
- {
- // find the cell that contains point p in its interior
- m_cellContain = m_pScene->m_dt.locate( pt );
- // erase old conflict hole info
- m_boundaryFacets.clear();
- m_conflictCells.clear();
- // show msg if point is outside the convex hull
- if( m_pScene->m_dt.is_infinite( m_cellContain ) )
- displayMessage( tr("Note: point is outside the convex hull.") );
- // compute the conflict hole induced by point p
- m_pScene->m_dt.find_conflicts( pt, // the point
- m_cellContain, // starting cell that must be in conflict
- std::back_inserter(m_boundaryFacets), // the facets on the boundary
- std::back_inserter(m_conflictCells) ); // the cells in conflict
- }
- /*************************************************************/
- /* Animation functions */
- void Viewer::toggleIncremental(bool on) {
- if( on ) { // play
- if( m_incrementalPts.isEmpty() ) {
- /* start play */
- if( m_pScene->m_dt.number_of_vertices() == 0 ) {
- CGAL::Random_points_in_cube_3<Point_3> pts_generator(1.0);
- CGAL::cpp0x::copy_n( pts_generator, 100, std::back_inserter(m_incrementalPts) );
- } else {
- for(QList<Vertex_handle>::iterator vit = m_pScene->m_vhArray.begin();
- vit < m_pScene->m_vhArray.end(); ++vit) {
- m_incrementalPts.push_back( (*vit)->point() );
- }//end-for
- // erase existing vertices
- initClean();
- }//end-if-pts
- // sorts points in a way that improves space locality
- CGAL::spatial_sort( m_incrementalPts.begin(), m_incrementalPts.end() );
- // set the current to "hightlight the new point"
- m_curStep = INIT;
- }/* else resume play */
- // set up the timer
- m_pTimer->start(1000);
- } else { // pause
- m_pTimer->stop();
- }
- // redraw
- updateGL();
- }
- void Viewer::stopIncremental() {
- if( !m_incrementalPts.isEmpty() ) {
- // will call toggleIncremental to stop the timer
- emit( stopIncAnimation() );
- // insert the rest points
- for(QList<Point_3>::iterator pit=m_incrementalPts.begin();
- pit < m_incrementalPts.end(); ++pit) {
- Vertex_handle hint;
- if( m_pScene->m_vhArray.isEmpty() ) {
- hint = m_pScene->m_dt.insert( *pit );
- } else {
- hint = m_pScene->m_vhArray.last();
- hint = m_pScene->m_dt.insert( *pit, hint );
- }
- m_pScene->m_vhArray.push_back( hint );
- }
- m_incrementalPts.clear();
- }
- // redraw
- updateGL();
- }
- void Viewer::incremental_insert() {
- Vertex_handle hint;
- if( !m_incrementalPts.isEmpty() ) {
- switch( m_curStep ) {
- case INIT: // end of INIT: get the next-to-insert point
- m_curIncPt = m_incrementalPts.at(0);
- m_curStep = NEWPT;
- break;
- case NEWPT: // end of NEWPT: locate the cell containing the point
- if( m_pScene->m_dt.is_valid() && m_pScene->m_dt.dimension() == 3 ) {
- computeConflict( m_curIncPt );
- m_curStep = CELL;
- }
- else {
- // popup the first point and insert it
- m_curIncPt = m_incrementalPts.takeFirst();
- if( m_pScene->m_vhArray.isEmpty() ) {
- hint = m_pScene->m_dt.insert( m_curIncPt );
- }
- else {
- hint = m_pScene->m_vhArray.last();
- hint = m_pScene->m_dt.insert( m_curIncPt, hint );
- }
- m_pScene->m_vhArray.push_back( hint );
- m_curStep = INIT;
- }
- break;
- case CELL: // end of CELL: compute the conflict region
- m_curStep = CONFLICT;
- break;
- case CONFLICT: // end of CONFLICT: do the insertion and go back to INIT
- // popup the first point and insert it
- m_curIncPt = m_incrementalPts.takeFirst();
- if( m_pScene->m_vhArray.isEmpty() ) {
- hint = m_pScene->m_dt.insert( m_curIncPt );
- } else {
- hint = m_pScene->m_vhArray.last();
- hint = m_pScene->m_dt.insert( m_curIncPt, hint );
- }
- m_pScene->m_vhArray.push_back( hint );
- m_curStep = INIT;
- break;
- }//end-of-switch
- } else {
- /* if finished, then start over */
- for(QList<Vertex_handle>::iterator vit = m_pScene->m_vhArray.begin();
- vit < m_pScene->m_vhArray.end(); ++vit) {
- m_incrementalPts.push_back( (*vit)->point() );
- }//end-for
- // erase existing vertices
- initClean();
- // set the current to "hightlight the new point"
- m_curStep = INIT;
- }
- // redraw
- updateGL();
- }