void ccGraphicalSegmentationTool::closeRectangle() { //only for rectangle selection in RUNNING mode if ((m_state & RECTANGLE) == 0 || (m_state & RUNNING) == 0) return; assert(m_segmentationPoly); unsigned vertCount = m_segmentationPoly->size(); if (vertCount < 4) { //first point only? we keep the real time update mechanism if (m_rectangularSelection) return; m_segmentationPoly->clear(); m_polyVertices->clear(); allowPolylineExport(false); } else { allowPolylineExport(true); } //stop m_state &= (~RUNNING); if (m_associatedWin) m_associatedWin->redraw(true, false); }
void ccGraphicalSegmentationTool::closePolyLine(int, int) { //only for polyline in RUNNING mode if ((m_state & POLYLINE) == 0 || (m_state & RUNNING) == 0) return; assert(m_segmentationPoly); unsigned vertCount = m_segmentationPoly->size(); if (vertCount < 4) { m_segmentationPoly->clear(); m_polyVertices->clear(); } else { //remove last point! m_segmentationPoly->resize(vertCount-1); //can't fail --> smaller m_segmentationPoly->setClosed(true); } //stop m_state &= (~RUNNING); //set the default import/export icon to 'export' mode loadSaveToolButton->setDefaultAction(actionExportSegmentationPolyline); allowPolylineExport(m_segmentationPoly->size() > 1); if (m_associatedWin) m_associatedWin->redraw(true, false); }
bool ccGraphicalSegmentationTool::start() { assert(m_polyVertices && m_segmentationPoly); if (!m_associatedWin) { ccLog::Warning("[Graphical Segmentation Tool] No associated window!"); return false; } m_segmentationPoly->clear(); m_polyVertices->clear(); allowPolylineExport(false); //the user must not close this window! m_associatedWin->setUnclosable(true); m_associatedWin->addToOwnDB(m_segmentationPoly); m_associatedWin->setPickingMode(ccGLWindow::NO_PICKING); pauseSegmentationMode(false); m_somethingHasChanged = false; reset(); return ccOverlayDialog::start(); }
ccGraphicalSegmentationTool::ccGraphicalSegmentationTool(QWidget* parent) : ccOverlayDialog(parent) , Ui::GraphicalSegmentationDlg() , m_somethingHasChanged(false) , m_state(0) , m_segmentationPoly(0) , m_polyVertices(0) , m_rectangularSelection(false) , m_deleteHiddenParts(false) { // Set QDialog background as transparent (DGM: doesn't work over an OpenGL context) //setAttribute(Qt::WA_NoSystemBackground); setupUi(this); setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); connect(inButton, SIGNAL(clicked()), this, SLOT(segmentIn())); connect(outButton, SIGNAL(clicked()), this, SLOT(segmentOut())); connect(razButton, SIGNAL(clicked()), this, SLOT(reset())); connect(validButton, SIGNAL(clicked()), this, SLOT(apply())); connect(validAndDeleteButton, SIGNAL(clicked()), this, SLOT(applyAndDelete())); connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel())); connect(pauseButton, SIGNAL(toggled(bool)), this, SLOT(pauseSegmentationMode(bool))); //selection modes connect(actionSetPolylineSelection, SIGNAL(triggered()), this, SLOT(doSetPolylineSelection())); connect(actionSetRectangularSelection, SIGNAL(triggered()), this, SLOT(doSetRectangularSelection())); //import/export options connect(actionUseExistingPolyline, SIGNAL(triggered()), this, SLOT(doActionUseExistingPolyline())); connect(actionExportSegmentationPolyline, SIGNAL(triggered()), this, SLOT(doExportSegmentationPolyline())); //add shortcuts addOverridenShortcut(Qt::Key_Space); //space bar for the "pause" button addOverridenShortcut(Qt::Key_Escape); //escape key for the "cancel" button addOverridenShortcut(Qt::Key_Return); //return key for the "apply" button addOverridenShortcut(Qt::Key_Delete); //delete key for the "apply and delete" button addOverridenShortcut(Qt::Key_Tab); //tab key to switch between rectangular and polygonal selection modes addOverridenShortcut(Qt::Key_I); //'I' key for the "segment in" button addOverridenShortcut(Qt::Key_O); //'O' key for the "segment out" button connect(this, SIGNAL(shortcutTriggered(int)), this, SLOT(onShortcutTriggered(int))); QMenu* selectionModeMenu = new QMenu(this); selectionModeMenu->addAction(actionSetPolylineSelection); selectionModeMenu->addAction(actionSetRectangularSelection); selectionModelButton->setDefaultAction(actionSetPolylineSelection); selectionModelButton->setMenu(selectionModeMenu); QMenu* importExportMenu = new QMenu(this); importExportMenu->addAction(actionUseExistingPolyline); importExportMenu->addAction(actionExportSegmentationPolyline); loadSaveToolButton->setMenu(importExportMenu); m_polyVertices = new ccPointCloud("vertices"); m_segmentationPoly = new ccPolyline(m_polyVertices); m_segmentationPoly->setForeground(true); m_segmentationPoly->setColor(ccColor::green); m_segmentationPoly->showColors(true); m_segmentationPoly->set2DMode(true); allowPolylineExport(false); }
void ccGraphicalSegmentationTool::updatePolyLine(int x, int y, Qt::MouseButtons buttons) { //process not started yet? if ((m_state & RUNNING) == 0) { return; } if (!m_associatedWin) { assert(false); return; } assert(m_polyVertices); assert(m_segmentationPoly); unsigned vertCount = m_polyVertices->size(); //new point (expressed relatively to the screen center) CCVector3 P(static_cast<PointCoordinateType>(x - m_associatedWin->width()/2), static_cast<PointCoordinateType>(m_associatedWin->height()/2 - y), 0); if (m_state & RECTANGLE) { //we need 4 points for the rectangle! if (vertCount != 4) m_polyVertices->resize(4); const CCVector3* A = m_polyVertices->getPointPersistentPtr(0); CCVector3* B = const_cast<CCVector3*>(m_polyVertices->getPointPersistentPtr(1)); CCVector3* C = const_cast<CCVector3*>(m_polyVertices->getPointPersistentPtr(2)); CCVector3* D = const_cast<CCVector3*>(m_polyVertices->getPointPersistentPtr(3)); *B = CCVector3(A->x,P.y,0); *C = P; *D = CCVector3(P.x,A->y,0); if (vertCount != 4) { m_segmentationPoly->clear(); if (!m_segmentationPoly->addPointIndex(0,4)) { ccLog::Error("Out of memory!"); allowPolylineExport(false); return; } m_segmentationPoly->setClosed(true); } } else if (m_state & POLYLINE) { if (vertCount < 2) return; //we replace last point by the current one CCVector3* lastP = const_cast<CCVector3*>(m_polyVertices->getPointPersistentPtr(vertCount-1)); *lastP = P; } m_associatedWin->redraw(true, false); }
void ccGraphicalSegmentationTool::pauseSegmentationMode(bool state) { assert(m_polyVertices && m_segmentationPoly); if (!m_associatedWin) return; if (state/*=activate pause mode*/) { m_state = PAUSED; if (m_polyVertices->size() != 0) { m_segmentationPoly->clear(); m_polyVertices->clear(); allowPolylineExport(false); } m_associatedWin->setInteractionMode(ccGLWindow::TRANSFORM_CAMERA); m_associatedWin->displayNewMessage("Segmentation [PAUSED]",ccGLWindow::UPPER_CENTER_MESSAGE,false,3600,ccGLWindow::MANUAL_SEGMENTATION_MESSAGE); m_associatedWin->displayNewMessage("Unpause to segment again",ccGLWindow::UPPER_CENTER_MESSAGE,true,3600,ccGLWindow::MANUAL_SEGMENTATION_MESSAGE); } else { m_state = STARTED; m_associatedWin->setInteractionMode(ccGLWindow::SEGMENT_ENTITY); if (m_rectangularSelection) { m_associatedWin->displayNewMessage("Segmentation [ON] (rectangular selection)",ccGLWindow::UPPER_CENTER_MESSAGE,false,3600,ccGLWindow::MANUAL_SEGMENTATION_MESSAGE); m_associatedWin->displayNewMessage("Left click: set opposite corners",ccGLWindow::UPPER_CENTER_MESSAGE,true,3600,ccGLWindow::MANUAL_SEGMENTATION_MESSAGE); } else { m_associatedWin->displayNewMessage("Segmentation [ON] (polygonal selection)",ccGLWindow::UPPER_CENTER_MESSAGE,false,3600,ccGLWindow::MANUAL_SEGMENTATION_MESSAGE); m_associatedWin->displayNewMessage("Left click: add contour points / Right click: close",ccGLWindow::UPPER_CENTER_MESSAGE,true,3600,ccGLWindow::MANUAL_SEGMENTATION_MESSAGE); } } //update mini-GUI pauseButton->blockSignals(true); pauseButton->setChecked(state); pauseButton->blockSignals(false); m_associatedWin->redraw(!state); }
void ccGraphicalSegmentationTool::doActionUseExistingPolyline() { MainWindow* mainWindow = MainWindow::TheInstance(); if (mainWindow) { ccHObject* root = mainWindow->dbRootObject(); ccHObject::Container polylines; if (root) { root->filterChildren(polylines,true,CC_TYPES::POLY_LINE); } if (!polylines.empty()) { ccEntityPickerDlg epDlg(polylines,false,0,this); if (!epDlg.exec()) return; int index = epDlg.getSelectedIndex(); assert(index >= 0 && index < static_cast<int>(polylines.size())); assert(polylines[index]->isA(CC_TYPES::POLY_LINE)); ccPolyline* poly = static_cast<ccPolyline*>(polylines[index]); //look for an asociated viewport ccHObject::Container viewports; if (poly->filterChildren(viewports,false,CC_TYPES::VIEWPORT_2D_OBJECT,true) == 1) { //shall we apply this viewport? if (QMessageBox::question(m_associatedWin,"Associated viewport","The selected polyline has an associated viewport: do you want to apply it?",QMessageBox::Yes,QMessageBox::No) == QMessageBox::Yes) { m_associatedWin->setViewportParameters(static_cast<cc2DViewportObject*>(viewports.front())->getParameters()); m_associatedWin->redraw(false); } } CCLib::GenericIndexedCloudPersist* vertices = poly->getAssociatedCloud(); bool mode3D = !poly->is2DMode(); //viewing parameters (for conversion from 3D to 2D) const double* MM = m_associatedWin->getModelViewMatd(); //viewMat const double* MP = m_associatedWin->getProjectionMatd(); //projMat const GLdouble half_w = static_cast<GLdouble>(m_associatedWin->width())/2; const GLdouble half_h = static_cast<GLdouble>(m_associatedWin->height())/2; int VP[4]; m_associatedWin->getViewportArray(VP); //force polygonal selection mode doSetPolylineSelection(); m_segmentationPoly->clear(); m_polyVertices->clear(); allowPolylineExport(false); //duplicate polyline 'a minima' (only points and indexes + closed state) if ( m_polyVertices->reserve(vertices->size()) && m_segmentationPoly->reserve(poly->size())) { for (unsigned i=0; i<vertices->size(); ++i) { CCVector3 P = *vertices->getPoint(i); if (mode3D) { GLdouble xp,yp,zp; gluProject(P.x,P.y,P.z,MM,MP,VP,&xp,&yp,&zp); P.x = static_cast<PointCoordinateType>(xp-half_w); P.y = static_cast<PointCoordinateType>(yp-half_h); P.z = 0; } m_polyVertices->addPoint(P); } for (unsigned j=0; j<poly->size(); ++j) m_segmentationPoly->addPointIndex(poly->getPointGlobalIndex(j)); m_segmentationPoly->setClosed(poly->isClosed()); if (m_segmentationPoly->isClosed()) { //stop m_state &= (~RUNNING); allowPolylineExport(m_segmentationPoly->size() > 1); } if (m_associatedWin) m_associatedWin->redraw(true, false); } else { ccLog::Error("Not enough memory!"); } } else { ccLog::Error("No polyline in DB!"); } } }
void ccGraphicalSegmentationTool::addPointToPolyline(int x, int y) { if ((m_state & STARTED) == 0) return; assert(m_polyVertices); assert(m_segmentationPoly); unsigned vertCount = m_polyVertices->size(); //particular case: we close the rectangular selection by a 2nd click if (m_rectangularSelection && vertCount == 4 && (m_state & RUNNING)) return; //new point CCVector3 P(static_cast<PointCoordinateType>(x), static_cast<PointCoordinateType>(y), 0); //CTRL key pressed at the same time? bool ctrlKeyPressed = m_rectangularSelection || ((QApplication::keyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier); //start new polyline? if (((m_state & RUNNING) == 0) || vertCount == 0 || ctrlKeyPressed) { //reset state m_state = (ctrlKeyPressed ? RECTANGLE : POLYLINE); m_state |= (STARTED | RUNNING); //reset polyline m_polyVertices->clear(); if (!m_polyVertices->reserve(2)) { ccLog::Error("Out of memory!"); allowPolylineExport(false); return; } //we add the same point twice (the last point will be used for display only) m_polyVertices->addPoint(P); m_polyVertices->addPoint(P); m_segmentationPoly->clear(); if (!m_segmentationPoly->addPointIndex(0,2)) { ccLog::Error("Out of memory!"); allowPolylineExport(false); return; } } else //next points in "polyline mode" only { //we were already in 'polyline' mode? if (m_state & POLYLINE) { if (!m_polyVertices->reserve(vertCount+1)) { ccLog::Error("Out of memory!"); allowPolylineExport(false); return; } //we replace last point by the current one CCVector3* lastP = const_cast<CCVector3*>(m_polyVertices->getPointPersistentPtr(vertCount-1)); *lastP = P; //and add a new (equivalent) one m_polyVertices->addPoint(P); if (!m_segmentationPoly->addPointIndex(vertCount)) { ccLog::Error("Out of memory!"); return; } m_segmentationPoly->setClosed(true); } else //we must change mode { assert(false); //we shouldn't fall here?! m_state &= (~RUNNING); addPointToPolyline(x,y); return; } } if (m_associatedWin) m_associatedWin->redraw(true, false); }