Salome HOME
Remove redundant code
[modules/geom.git] / src / EntityGUI / EntityGUI_FeatureDetectorDlg.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // GEOM GEOMGUI : GUI for Geometry component
24 // File   : EntityGUI_SketcherDlg.cxx
25 // Author : Renaud NEDELEC, Open CASCADE S.A.S.
26
27 // SALOME includes
28 #include "EntityGUI_FeatureDetectorDlg.h"
29 #include "ShapeRec_FeatureDetector.hxx"
30 #include "GEOM_Constants.h"
31
32 #include <OCCViewer_ViewWindow.h>
33 #include <OCCViewer_ViewManager.h>
34
35 #include <SOCC_ViewModel.h>
36
37 #include <DlgRef.h>
38 #include <GeometryGUI.h>
39 #include <EntityGUI.h>
40 #include <GEOMBase.h>
41
42 #include <SUIT_Desktop.h>
43 #include <SUIT_ResourceMgr.h>
44 #include <SUIT_Session.h>
45 #include <SUIT_ViewWindow.h>
46 #include <SalomeApp_Application.h>
47 #include <LightApp_Application.h>
48 #include <LightApp_SelectionMgr.h>
49
50 #include <SALOME_ListIO.hxx>
51
52 #include <SalomeApp_Study.h>
53
54 #include <utilities.h>
55 #include <Precision.hxx>
56
57 // OCCT includes
58 #include <gp_Pnt.hxx>
59 #include <TopoDS_Shape.hxx>
60 #include <TopoDS_Wire.hxx>
61
62 #include <BRepBuilderAPI_MakeVertex.hxx>
63 #include <BRepBuilderAPI_MakeFace.hxx>
64 #include <BRepBuilderAPI_MakePolygon.hxx>
65 #include <BRepBuilderAPI_Transform.hxx>
66
67 #include <AIS_TexturedShape.hxx>
68 #include <TCollection_AsciiString.hxx>
69 #include <StdSelect_DisplayMode.hxx>
70
71 #include <Graphic3d_MaterialAspect.hxx>
72
73 // C++ includes
74 #include <set>
75 #include <utility>
76
77 // boost includes
78 #include <boost/utility.hpp>
79
80 // Constructors
81 enum{
82   CONTOURS,
83   CORNERS,
84   LINES
85 };
86
87 enum {
88   KERNEL_SIZE,
89   FIND_CONTOURS_METHOD,
90   QUALITY_LEVEL,
91   MIN_DISTANCE,
92   TYPE_CRITERIA,
93   MAX_ITER,
94   EPSILON,
95   LOW_THRESHOLD,
96   RATIO,
97   L2GRADIENT,
98   SMOOTH_SIZE,
99   HBINS,
100   SBINS,
101   HIST_TYPE,
102   THRESHOLD_VALUE,
103   MAX_THRESHOLD,
104 };
105
106 // // // View
107 // // enum {
108 // //   XY,
109 // //   YZ,
110 // //   XZ
111 // // };
112   
113
114 //=================================================================================
115 // class    : EntityGUI_FeatureDetectorDlg()
116 // purpose  : Constructs a EntityGUI_FeatureDetectorDlg which is a child of 'parent', with the
117 //            name 'name' and widget flags set to 'f'.
118 //            The dialog will by default be modeless, unless you set 'modal' to
119 //            TRUE to construct a modal dialog.
120 //=================================================================================
121 EntityGUI_FeatureDetectorDlg::EntityGUI_FeatureDetectorDlg( GeometryGUI* theGeometryGUI, QWidget* parent,
122                                               bool modal, Qt::WindowFlags fl)
123   : GEOMBase_Skeleton(theGeometryGUI, parent, modal, fl) 
124 {
125   QPixmap image0(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT")));
126   QPixmap image1(SUIT_Session::session()->resourceMgr()->loadPixmap("OCCViewer", tr("ICON_OCCVIEWER_VIEW_DUMP")));
127
128   setWindowTitle(tr("GEOM_DETECT_TITLE"));
129   
130   /***************************************************************/
131   
132   mainFrame()->GroupConstructors->setTitle(tr("GEOM_FEATURES"));
133   mainFrame()->RadioButton1->setText(tr("GEOM_CONTOURS"));
134   mainFrame()->RadioButton2->setText(tr("GEOM_CORNERS"));
135   mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
136   mainFrame()->RadioButton3->close();
137   
138 //   myViewGroup = new DlgRef_3Radio(centralWidget());
139 //   myViewGroup->GroupBox1->setTitle(tr("GEOM_VIEW"));
140 //   myViewGroup->RadioButton1->setText(tr( "GEOM_TOP"  ));
141 //   myViewGroup->RadioButton2->setText(tr( "GEOM_FRONT"));
142 //   myViewGroup->RadioButton3->setText(tr( "GEOM_LEFT" ));
143 //   myViewButtonGroup = new QButtonGroup( this );
144 //   myViewButtonGroup->addButton( myViewGroup->RadioButton1, XY ); // Top view
145 //   myViewButtonGroup->addButton( myViewGroup->RadioButton2, YZ ); // Front View
146 //   myViewButtonGroup->addButton( myViewGroup->RadioButton3, XZ ); // Left View
147 //   
148 //   myViewGroup->hide();
149   
150   // Widgets for the selection of the picture and the Region Of Interest 
151   
152   
153   mySelectionGroup = new DlgRef_1Sel1Frame(centralWidget());
154
155   mySelectionGroup->PushButton1->setIcon(image0);
156   mySelectionGroup->PushButton1->setCheckable(true);
157   mySelectionGroup->PushButton1->setAutoExclusive(true);
158   
159   mySelectionGroup->PushButton2->setIcon(image1);
160   mySelectionGroup->PushButton2->setCheckable(true);
161   mySelectionGroup->PushButton2->setAutoExclusive(true);
162
163   mySelectionGroup->TextLabel1->setText(tr( "GEOM_PICTURE" ));
164   mySelectionGroup->FrameLabel->setText("");
165   
166   myOutputGroup = new DlgRef_3Radio(centralWidget());
167   myOutputGroup->GroupBox1->setTitle(tr("GEOM_DETECT_OUTPUT"));
168   myOutputGroup->RadioButton2->setText(tr( "GEOM_POLYLINE"  ));
169   myOutputGroup->RadioButton1->setText(tr( "GEOM_SPLINE"));
170   myOutputGroup->RadioButton3->hide();
171   
172 //   myOutputGroup->hide(); //caché pour la demo
173     
174   // Parameters 
175   QGridLayout* parametersLayout = new QGridLayout();
176   parametersLayout->setMargin(9);
177   QComboBox* kernelSize = new QComboBox();
178   kernelSize->addItems( QStringList() << "3" << "5" << "7" );
179   myWidgets.insert( KERNEL_SIZE, kernelSize );
180   myUseROI = new QCheckBox( tr("USE_ROI") );
181   myUseROI->setChecked( true );
182
183   parametersLayout->addWidget( new QLabel( tr("KERNEL_SIZE") ), 0, 0 );
184   parametersLayout->addWidget( kernelSize, 0, 1 );
185   parametersLayout->addWidget( myUseROI, 0, 2 );
186
187   // Corners Parameters 
188   myCornersParameters = new QFrame();
189   myCornersParameters->setFrameStyle(QFrame::NoFrame);
190   QDoubleSpinBox* qualityLevel = new QDoubleSpinBox();
191   qualityLevel->setValue( 0.2 );
192   qualityLevel->setSingleStep( 0.1 );
193   qualityLevel->setRange( 0.01, 0.99 );
194   myWidgets.insert( QUALITY_LEVEL, qualityLevel );
195   QDoubleSpinBox* minDistance = new QDoubleSpinBox();
196   minDistance->setValue( 1 );
197   myWidgets.insert( MIN_DISTANCE, minDistance );
198   QComboBox* typeCriteria = new QComboBox();
199   typeCriteria->addItems( QStringList() << tr("CV_TERMCRIT_ITER") << tr("CV_TERMCRIT_EPS") << tr("CV_TERMCRIT_ITER | CV_TERMCRIT_EPS") );
200   typeCriteria->setCurrentIndex( 2 );
201   myWidgets.insert( TYPE_CRITERIA, typeCriteria );
202   QSpinBox* maxIter = new QSpinBox();
203   maxIter->setValue( 20 );
204   maxIter->setRange( 1, 100 );
205   myWidgets.insert( MAX_ITER, maxIter );
206   QDoubleSpinBox* epsilon = new QDoubleSpinBox();
207   epsilon->setValue( 0.03 );
208   epsilon->setSingleStep( 0.01 );
209   myWidgets.insert( EPSILON, epsilon );
210
211   QGridLayout* cornersLayout = new QGridLayout();
212   cornersLayout->setMargin( 0 );
213   cornersLayout->addWidget( new QLabel( tr("QUALITY_LEVEL") ), 0, 0 );
214   cornersLayout->addWidget( qualityLevel, 0, 1 );
215   cornersLayout->addWidget( new QLabel( tr("MIN_DISTANCE") ), 0, 2 );
216   cornersLayout->addWidget( minDistance, 0 ,3 );
217   cornersLayout->addWidget( new QLabel( tr("TYPE_CRITERIA") ), 1, 0 );
218   cornersLayout->addWidget( typeCriteria, 1, 1, 1, 3 );
219   cornersLayout->addWidget( new QLabel( tr("MAX_ITER") ), 2, 0 );
220   cornersLayout->addWidget( maxIter, 2, 1 );
221   cornersLayout->addWidget( new QLabel( tr("EPSILON") ), 2, 2 );
222   cornersLayout->addWidget( epsilon, 2 , 3 );
223
224   myCornersParameters->setLayout( cornersLayout );
225
226   // Contours Parameters
227   myContoursParameters = new QFrame();
228   myContoursParameters->setFrameStyle(QFrame::NoFrame);
229
230   QComboBox* findContoursMethod = new QComboBox();
231   findContoursMethod->addItems( QStringList() << tr("CV_CHAIN_APPROX_NONE") << tr("CV_CHAIN_APPROX_SIMPLE") << tr("CV_CHAIN_APPROX_TC89_L1") << tr("CV_CHAIN_APPROX_TC89_KCOS") );
232   myWidgets.insert( FIND_CONTOURS_METHOD, findContoursMethod );
233
234   myCannyParameters = new QFrame();
235   myCannyParameters->setFrameStyle(QFrame::NoFrame);
236   QSpinBox* threshold = new QSpinBox();
237   threshold->setRange( 0, 255 );
238   threshold->setValue( 100 );
239   myWidgets.insert( LOW_THRESHOLD, threshold );
240   QSpinBox* ratio = new QSpinBox();
241   ratio->setValue( 3 );
242   ratio->setRange( 0, 255 );
243   myWidgets.insert( RATIO, ratio );
244   QCheckBox* L2gradient = new QCheckBox(tr("L2GRADIENT"));
245   L2gradient->setChecked(true);
246   myWidgets.insert( L2GRADIENT, L2gradient );
247
248   QGridLayout* cannyLayout = new QGridLayout();
249   cannyLayout->setMargin( 0 );
250   cannyLayout->addWidget( new QLabel( tr("LOWTHRESHOLD") ), 0, 0 );
251   cannyLayout->addWidget( threshold, 0, 1 );
252   cannyLayout->addWidget( new QLabel( tr("RATIO") ), 0, 2 );
253   cannyLayout->addWidget( ratio, 0, 3 );
254   cannyLayout->addWidget( L2gradient, 1, 0 );
255
256   myCannyParameters->setLayout( cannyLayout );
257   myCannyParameters->setHidden( true );
258
259   myColorFilterParameters = new QFrame();
260   myColorFilterParameters->setFrameStyle(QFrame::NoFrame);
261
262   QSpinBox* smoothSize = new QSpinBox();
263   smoothSize->setValue( 3 );
264   smoothSize->setSingleStep( 2 );
265   smoothSize->setRange( 1, 1000 );
266   myWidgets.insert( SMOOTH_SIZE, smoothSize );
267   QSpinBox* hbins = new QSpinBox();
268   hbins->setValue( 30 );
269   hbins->setRange( 0, 179 );
270   myWidgets.insert( HBINS, hbins );
271   QSpinBox* sbins = new QSpinBox();
272   sbins->setValue( 32 );
273   sbins->setRange( 0, 255 );
274   myWidgets.insert( SBINS, sbins );
275   QComboBox* histType = new QComboBox();
276   histType->addItems( QStringList() << tr("CV_HIST_ARRAY") << tr("CV_HIST_SPARSE") );
277   myWidgets.insert( HIST_TYPE, histType );
278   QDoubleSpinBox* thresholdValue = new QDoubleSpinBox();
279   thresholdValue->setRange( 0, 254 );
280   // 1 is a good default value for the threshold. It means that we are very permissive
281   // about what will be considered INSIDE the zone we want to find the frontier of
282   // This makes the algorithm more robust against a bit inhomogeneous parts in the zone
283   // that we want to delimitate.
284   // The drawback is if we want to delimitate a zone wich color is very similar to the zone
285   // we consider as the OUTSIDE, the result will be bad.
286   // The current use cases are more of the first form : 
287   //  - Strongly contrasted INSIDE and OUTSIDE zones
288   //  - Small inhomogenities in each zone
289   thresholdValue->setValue( 1 );
290   myWidgets.insert( THRESHOLD_VALUE, thresholdValue );
291   QDoubleSpinBox* maxThreshold = new QDoubleSpinBox();
292   maxThreshold->setRange( 1, 255 );
293   maxThreshold->setValue( 255 );
294   myWidgets.insert( MAX_THRESHOLD, maxThreshold );
295
296   QGridLayout* colorFilterLayout = new QGridLayout();
297   colorFilterLayout->setMargin( 0 );
298   colorFilterLayout->addWidget( new QLabel( tr("SMOOTH_SIZE") ), 0, 0 );
299   colorFilterLayout->addWidget( smoothSize, 0, 1 );
300   colorFilterLayout->addWidget( new QLabel( tr("HBINS") ), 1, 0 );
301   colorFilterLayout->addWidget( hbins, 1, 1 );
302   colorFilterLayout->addWidget( new QLabel( tr("SBINS") ), 1, 2 );
303   colorFilterLayout->addWidget( sbins, 1, 3 );
304   colorFilterLayout->addWidget( new QLabel( tr("HIST_TYPE") ), 2, 0 );
305   colorFilterLayout->addWidget( histType, 2, 1, 1, 3 );
306   colorFilterLayout->addWidget( new QLabel( tr("THRESHOLD_VALUE") ), 3, 0 );
307   colorFilterLayout->addWidget( thresholdValue, 3, 1 );
308   colorFilterLayout->addWidget( new QLabel( tr("MAX_THRESHOLD") ), 3, 2 );
309   colorFilterLayout->addWidget( maxThreshold, 3, 3 );
310
311   myColorFilterParameters->setLayout( colorFilterLayout );
312   QGridLayout* contoursLayout = new QGridLayout();
313   contoursLayout->setMargin( 0 );
314   contoursLayout->addWidget( new QLabel( tr("FIND_CONTOURS_METHOD") ), 0, 0 );
315   contoursLayout->addWidget( findContoursMethod, 0, 1 );
316   contoursLayout->addWidget( myCannyParameters, 1, 0, 1, 3 );
317   contoursLayout->addWidget( myColorFilterParameters, 1, 0, 1, 3  );
318
319   myContoursParameters->setLayout( contoursLayout );
320
321   parametersLayout->addWidget( myCornersParameters, 1, 0, 1, 3 );
322   parametersLayout->addWidget( myContoursParameters, 1, 0, 1, 3 );
323
324   QVBoxLayout* layout = new QVBoxLayout(centralWidget());
325   layout->setMargin(0); layout->setSpacing(6);
326 //   layout->addWidget( myViewGroup);
327   layout->addLayout( parametersLayout );
328   layout->addWidget( mySelectionGroup);
329   layout->addWidget( myOutputGroup);
330   
331 //   mainFrame()->GroupBoxName->hide();
332   
333   // Build an instance of detection used to perform image processing operations
334   myDetector = new ShapeRec_FeatureDetector();
335   
336   setHelpFileName( "shape_recognition_page.html" );
337   
338   Init();
339   
340 }
341
342 //=================================================================================
343 // function : ~EntityGUI_FeatureDetectorDlg()
344 // purpose  : Destroys the object and frees any allocated resources
345 //=================================================================================
346 EntityGUI_FeatureDetectorDlg::~EntityGUI_FeatureDetectorDlg()
347 {
348   delete myDetector;
349 }
350
351 //=================================================================================
352 // function : Init()
353 // purpose  :
354 //=================================================================================
355 void EntityGUI_FeatureDetectorDlg::Init()
356 {
357   connect( myGeomGUI,         SIGNAL( SignalCloseAllDialogs() ), this, SLOT( ClickOnCancel() ) );
358   connect( buttonOk(),        SIGNAL( clicked() ),               this, SLOT( ClickOnOk() ) );
359   connect( buttonApply(),     SIGNAL( clicked() ),               this, SLOT( ClickOnApply() ) );
360   connect( myUseROI,          SIGNAL( toggled(bool) ),           this, SLOT( onCheckBoxClicked(bool) ) );
361   connect( this,              SIGNAL(constructorsClicked(int)),  this, SLOT(ConstructorsClicked(int))); 
362   connect( mySelectionGroup->PushButton2,      SIGNAL( clicked() ),               this, SLOT( onButtonClicked() ) );
363   connect( mySelectionGroup->PushButton1,       SIGNAL( clicked() ),               this, SLOT( onButtonClicked() ) );  
364 //   connect( myViewButtonGroup, SIGNAL( buttonClicked( int ) ),    this, SLOT( onViewClicked( int ) ) );
365   connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ),this, SLOT( SelectionIntoArgument() ) );
366   
367   myConstructorId = 0;
368   mySelectionGroup->PushButton1->click();
369   
370 //   SetEditCurrentArgument();
371   SelectionIntoArgument();
372   
373   initName(tr("GEOM_CONTOURS")); 
374   resize(100,100);
375   
376 //   myViewGroup->RadioButton1->setChecked(true);
377   myOutputGroup->RadioButton1->setChecked(true);
378   
379   gp_Pnt aOrigin = gp_Pnt(0, 0, 0);
380   gp_Dir aDirZ = gp_Dir(0, 0, 1);
381   gp_Dir aDirX = gp_Dir(1, 0, 0);
382   
383   aGlobalCS = gp_Ax3(aOrigin, aDirZ, aDirX);
384   
385   myStartPnt = gp_Pnt(0,0,0);
386   myEndPnt = myStartPnt;
387   
388   myGeomGUI->SetWorkingPlane( aGlobalCS );
389   myGeomGUI->ActiveWorkingPlane();
390   
391   ConstructorsClicked(myConstructorId);
392 }
393
394 //=================================================================================
395 // function : SelectionIntoArgument()
396 // purpose  : Called when selection as changed or other case
397 //=================================================================================
398 void EntityGUI_FeatureDetectorDlg::SelectionIntoArgument()
399 {
400   
401   // TODO supprimer les lignes qui ne servent Ã  rien le cas Ã©chéant
402   SUIT_ViewWindow*       theViewWindow  = getDesktop()->activeWindow();
403   SOCC_Viewer* soccViewer = (SOCC_Viewer*)(theViewWindow->getViewManager()->getViewModel());
404
405   if (!myEditCurrentArgument->isEnabled())
406     return;
407   
408   myEditCurrentArgument->setText( "" );
409
410   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
411   SALOME_ListIO aSelList;
412   aSelMgr->selectedObjects(aSelList);
413   SALOME_ListIteratorOfListIO anIt( aSelList );
414   
415   for( ; anIt.More(); anIt.Next() )
416     if( !anIt.Value().IsNull() )
417     {
418       myFaceEntry = anIt.Value()->getEntry();
419     }
420
421   if (aSelList.Extent() != 1) {
422     if (myEditCurrentArgument == mySelectionGroup->LineEdit1) 
423       myFace.nullify();
424     return;
425   }
426
427   TopAbs_ShapeEnum aNeedType = TopAbs_FACE ;
428   GEOM::GeomObjPtr aSelectedObject = getSelected( aNeedType );
429   TopoDS_Shape aShape;
430   if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aShape ) && !aShape.IsNull() ) {
431     QString aName = GEOMBase::GetName( aSelectedObject.get() );
432     myEditCurrentArgument->setText( aName );
433     
434     if ( myEditCurrentArgument == mySelectionGroup->LineEdit1 ) {
435       myFace = aSelectedObject;
436
437       SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
438       if ( !study ) return;
439       LightApp_Application* app = ::qobject_cast<LightApp_Application*>( study->application() );
440       if ( !app ) return;
441       SUIT_ViewManager* vm = app->activeViewManager();
442       if ( !vm ) return;
443       PropMap propMap = study->getObjectProperties( vm->getGlobalId(), myFaceEntry );
444       QString theImgFileName = propMap.value( GEOM::propertyName( GEOM::Texture ) ).toString();
445       if ( theImgFileName.isEmpty() )
446         return;
447
448       // Setting the image caracteristics
449       myDetector->SetPath( theImgFileName.toStdString() );
450       height            =  myDetector->GetImgHeight();
451       width             =  myDetector->GetImgWidth();
452       pictureLeft       = -0.5 * width;              // X coordinate of the top left  corner of the background image in the view
453       pictureTop        =  0.5 * height;             // Y coordinate of both top corners
454       
455     } 
456   }
457   
458 }
459
460 //=================================================================================
461 // function : acceptMouseEvent()
462 // purpose  :
463 //=================================================================================
464 bool EntityGUI_FeatureDetectorDlg::acceptMouseEvent() const
465
466   return mySelectionGroup->PushButton2->isChecked();  
467 }
468
469 //=======================================================================
470 // function : ClickOnOk()
471 // purpose  :
472 //=======================================================================
473 void EntityGUI_FeatureDetectorDlg::ClickOnOk()
474 {
475   setIsApplyAndClose( true );
476   if (onAccept())
477     ClickOnCancel();
478 }
479
480 //=================================================================================
481 // function : ClickOnApply()
482 // purpose  :
483 //=================================================================================
484 bool EntityGUI_FeatureDetectorDlg::ClickOnApply()
485 {
486   if (!onAccept())
487     return false;
488
489 //   initName();
490   ConstructorsClicked(getConstructorId());
491   return true;
492 }
493
494 //=================================================================================
495 // function : onConstructorClicked(int)
496 // purpose  :
497 //=================================================================================
498 void EntityGUI_FeatureDetectorDlg::ConstructorsClicked(int id)
499 {
500   MESSAGE("Constructor id ="<<id)
501   myConstructorId = id;
502   switch (id)
503   {
504     case CORNERS:
505       myCornersParameters->show();
506       myContoursParameters->hide();
507 //       myViewGroup->show();
508 //       mySelectionGroup->show();
509       myOutputGroup->hide();
510 //       mySelectionGroup->TextLabel2->setText(tr("GEOM_DETECT_ZONE"));
511       initName(tr("GEOM_CORNERS"));
512       break;
513     case CONTOURS:
514       myCornersParameters->hide();
515       myContoursParameters->show();
516 //       myViewGroup->hide();
517 //       mySelectionGroup->hide();
518 //       mySelectionGroup->show();
519       myOutputGroup->show();
520       mySelectionGroup->TextLabel2->setText(tr("GEOM_COLOR_FILTER"));
521       initName(tr("GEOM_CONTOURS"));
522       break;
523     case LINES:
524 //       myViewGroup->hide();
525 //       mySelectionGroup->hide();
526 //       mySelectionGroup->show();
527       myOutputGroup->hide();
528       mySelectionGroup->TextLabel2->setText(tr(""));
529       initName(tr("GEOM_LINES"));
530       break;
531   }
532 }
533
534 // //=================================================================================
535 // // function : onViewClicked()
536 // // purpose  :
537 // //=================================================================================
538 // void EntityGUI_FeatureDetectorDlg::onViewClicked(int id)
539 // {
540 //   gp_Pnt aOrigin = gp_Pnt(0, 0, 0);
541 //   gp_Dir aDirZ;
542 //   gp_Dir aDirX;
543 //   
544 //   switch(id)
545 //   {
546 //     case XY:
547 //         aDirZ = gp_Dir(0, 0, 1);
548 //         aDirX = gp_Dir(1, 0, 0);
549 //       break;
550 //     case YZ:
551 //         aDirZ = gp_Dir(1, 0, 0);
552 //         aDirX = gp_Dir(0, 1, 0);
553 //       break;
554 //     case XZ:
555 //         aDirZ = gp_Dir(0, -1, 0);
556 //         aDirX = gp_Dir(1, 0 , 0);
557 //       break;
558 //   }
559 //   
560 //   myWPlane = gp_Ax3(aOrigin, aDirZ, aDirX);
561 //   myGeomGUI->SetWorkingPlane( myWPlane );
562 //   myGeomGUI->ActiveWorkingPlane();
563 //   
564 // }
565
566 //=================================================================================
567 // function : onButtonClicked()
568 // purpose  :
569 //=================================================================================
570 void EntityGUI_FeatureDetectorDlg::onButtonClicked()
571 {
572   QPushButton* send = (QPushButton*)sender();
573   if (send == mySelectionGroup->PushButton2)
574   {
575     mySelectionGroup->LineEdit1->setEnabled(false);
576   }
577   else if (send == mySelectionGroup->PushButton1)
578   {
579     myStartPnt = gp_Pnt(0,0,0);
580     myEndPnt   = myStartPnt;
581     myEditCurrentArgument = mySelectionGroup->LineEdit1;
582     mySelectionGroup->LineEdit1->setEnabled(true);   
583   }
584 }
585
586 //=================================================================================
587 // function : onCheckBoxClicked(bool)
588 // purpose  :
589 //=================================================================================
590 void EntityGUI_FeatureDetectorDlg::onCheckBoxClicked( bool isChecked )
591 {
592   mySelectionGroup->TextLabel2->setVisible( isChecked );
593   mySelectionGroup->Frame->setVisible( isChecked );
594   mySelectionGroup->PushButton2->setVisible( isChecked );
595   myCannyParameters->setHidden( isChecked );
596   myColorFilterParameters->setHidden( !isChecked );
597 }
598
599 //=================================================================================
600 // function : parametersChanged()
601 // purpose  :
602 //=================================================================================
603 ShapeRec_Parameters* EntityGUI_FeatureDetectorDlg::parametersChanged()
604 {
605   ShapeRec_Parameters* aParameters = new ShapeRec_Parameters();
606
607   if ( myConstructorId == CORNERS ) {
608     ShapeRec_CornersParameters* aCornersParameters = dynamic_cast<ShapeRec_CornersParameters*>( aParameters );
609     if ( !aCornersParameters ) aCornersParameters = new ShapeRec_CornersParameters();
610     aCornersParameters->qualityLevel = (dynamic_cast<QDoubleSpinBox*>(myWidgets[QUALITY_LEVEL]))->value();
611     aCornersParameters->minDistance  = (dynamic_cast<QDoubleSpinBox*>(myWidgets[MIN_DISTANCE]))->value();
612     switch ( (dynamic_cast<QComboBox*>(myWidgets[TYPE_CRITERIA]))->currentIndex() ) {
613     case 0: aCornersParameters->typeCriteria = CV_TERMCRIT_ITER;
614     case 1: aCornersParameters->typeCriteria = CV_TERMCRIT_EPS;
615     case 2: aCornersParameters->typeCriteria = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS;
616     }
617     aCornersParameters->maxIter = (dynamic_cast<QSpinBox*>(myWidgets[MAX_ITER]))->value();
618     aCornersParameters->epsilon = (dynamic_cast<QDoubleSpinBox*>(myWidgets[EPSILON]))->value();
619     aParameters = aCornersParameters;
620   }
621   else if ( myConstructorId == CONTOURS ) {
622     if ( !myUseROI->isChecked() ) { 
623       ShapeRec_CannyParameters* aCannyParameters = dynamic_cast<ShapeRec_CannyParameters*>( aParameters );
624       if ( !aCannyParameters ) aCannyParameters = new ShapeRec_CannyParameters();
625       aCannyParameters->lowThreshold = (dynamic_cast<QSpinBox*>(myWidgets[LOW_THRESHOLD]))->value();
626       aCannyParameters->ratio        = (dynamic_cast<QSpinBox*>(myWidgets[RATIO]))->value();
627       aCannyParameters->L2gradient   = (dynamic_cast<QCheckBox*>(myWidgets[L2GRADIENT]))->isChecked();
628       aParameters = aCannyParameters;
629     }
630     else {
631       ShapeRec_ColorFilterParameters* aColorFilterParameters = dynamic_cast<ShapeRec_ColorFilterParameters*>( aParameters );
632       if ( !aColorFilterParameters ) aColorFilterParameters = new ShapeRec_ColorFilterParameters();
633       int aSmoothSize = (dynamic_cast<QSpinBox*>(myWidgets[SMOOTH_SIZE]))->value();
634       aColorFilterParameters->smoothSize  = aSmoothSize % 2 == 0 ? aSmoothSize - 1 : aSmoothSize;
635       aColorFilterParameters->histSize[0] = (dynamic_cast<QSpinBox*>(myWidgets[HBINS]))->value();
636       aColorFilterParameters->histSize[1] = (dynamic_cast<QSpinBox*>(myWidgets[SBINS]))->value();
637       switch ( (dynamic_cast<QComboBox*>(myWidgets[HIST_TYPE]))->currentIndex() ) {
638       case 0: aColorFilterParameters->histType = CV_HIST_ARRAY;  break;
639       case 1: aColorFilterParameters->histType = CV_HIST_SPARSE; break;
640       }
641       aColorFilterParameters->threshold    = (dynamic_cast<QDoubleSpinBox*>(myWidgets[THRESHOLD_VALUE]))->value();
642       aColorFilterParameters->maxThreshold = (dynamic_cast<QDoubleSpinBox*>(myWidgets[MAX_THRESHOLD]))->value();
643       aParameters = aColorFilterParameters;
644     }
645   }
646  
647   aParameters->kernelSize = ( (dynamic_cast<QComboBox*>(myWidgets[KERNEL_SIZE]))->currentText() ).toInt();
648   switch ( (dynamic_cast<QComboBox*>(myWidgets[FIND_CONTOURS_METHOD]))->currentIndex() ) {
649   case 0: aParameters->findContoursMethod = CV_CHAIN_APPROX_NONE;      break;
650   case 1: aParameters->findContoursMethod = CV_CHAIN_APPROX_SIMPLE;    break;
651   case 2: aParameters->findContoursMethod = CV_CHAIN_APPROX_TC89_L1;   break;
652   case 3: aParameters->findContoursMethod = CV_CHAIN_APPROX_TC89_KCOS; break;
653   }
654
655   return aParameters;
656 }
657
658 //=================================================================================
659 // function : setStartPnt( const QPoint& )
660 // purpose  :
661 //=================================================================================
662 void EntityGUI_FeatureDetectorDlg::setStartPnt(const gp_Pnt& theStartPnt)
663 {
664   myStartPnt = theStartPnt;
665   MESSAGE("myStartPnt = ("<<theStartPnt.X()<<", "<<theStartPnt.Y()<<")")
666 }
667
668 //=================================================================================
669 // function : setEndPnt( const QPoint& )
670 // purpose  :
671 //=================================================================================
672 void EntityGUI_FeatureDetectorDlg::setEndPnt(const gp_Pnt& theEndPnt)
673 {
674   myEndPnt = theEndPnt;
675   MESSAGE("myEndPnt = ("<<theEndPnt.X()<<", "<<theEndPnt.Y()<<")")
676   if (setSelectionRect() && myDetector->GetImgHeight() > 0)
677     showImageSample();
678 }
679
680 //=================================================================================
681 // function : setSelectionRect()
682 // purpose  :
683 //=================================================================================
684 bool EntityGUI_FeatureDetectorDlg::setSelectionRect()
685
686   // Set detection rectangle in the background image coordinates system
687   double left    = std::min( myStartPnt.X(), myEndPnt.X() );
688   double top     = std::max( myStartPnt.Y(), myEndPnt.Y() );
689   double right   = std::max( myStartPnt.X(), myEndPnt.X() );
690   double bottom  = std::min( myStartPnt.Y(), myEndPnt.Y() );
691   
692   QPoint topLeft     = QPoint(left  - pictureLeft, pictureTop - top   );
693   QPoint bottomRight = QPoint(right - pictureLeft, pictureTop - bottom);
694   
695   myRect = QRect(topLeft, bottomRight);
696   
697   return (!myRect.isEmpty() && myRect.width() > 1);
698 }
699
700 //=================================================================================
701 // function : showImageSample()
702 // purpose  : Display a preview of the image sample selected by the user
703 //=================================================================================
704 void EntityGUI_FeatureDetectorDlg::showImageSample()
705
706   // Cropp the image to the selection rectangle given by the user
707   myDetector->SetROI( myRect ); 
708   std::string samplePicturePath = myDetector->CroppImage();
709   
710   // Display the result
711   QPixmap pixmap(QString(samplePicturePath.c_str()));
712   mySelectionGroup->FrameLabel->setPixmap(pixmap);
713   mySelectionGroup->FrameLabel->setMask(pixmap.mask());
714 }
715
716 //=================================================================================
717 // function : createOperation
718 // purpose  :
719 //=================================================================================
720 GEOM::GEOM_IOperations_ptr EntityGUI_FeatureDetectorDlg::createOperation()
721 {
722   return myGeomGUI->GetGeomGen()->GetIShapesOperations( getStudyId() );
723 }
724
725 //=================================================================================
726 // function : execute()
727 // purpose  :
728 //=================================================================================
729 bool EntityGUI_FeatureDetectorDlg::execute( ObjectList& objects )
730 {
731   bool res = false;
732   
733   GEOM::GEOM_IBasicOperations_var  aBasicOperations  = myGeomGUI->GetGeomGen()->GetIBasicOperations( getStudyId() );
734   GEOM::GEOM_IShapesOperations_var aShapesOperations = GEOM::GEOM_IShapesOperations::_narrow( getOperation() );
735
736   ShapeRec_Parameters* parameters = parametersChanged();
737   if ( !parameters ) parameters = new ShapeRec_Parameters();
738
739   bool useROI = myUseROI->isChecked() && !myRect.isEmpty();
740   try {
741     if (myConstructorId == CORNERS)
742     {
743       double subPictureLeft;
744       double subPictureTop;
745       if( useROI )
746       {
747         subPictureLeft    = myStartPnt.X();                
748         subPictureTop     = myStartPnt.Y();
749       }
750       else
751       {
752         subPictureLeft    = pictureLeft;
753         subPictureTop     = pictureTop;
754       }
755       myDetector->ComputeCorners( useROI, parameters );
756       CvPoint2D32f* corners     = myDetector->GetCorners();
757       int cornerCount           = myDetector->GetCornerCount();
758       int i;
759     
760       // Build the geom objects associated to the detected corners and returned by execute   
761       if( !aBasicOperations->_is_nil() && !aShapesOperations->_is_nil() ) 
762       {
763         GEOM::GEOM_Object_var  aGeomCorner;
764         GEOM::ListOfGO_var     geomCorners = new GEOM::ListOfGO();
765         geomCorners->length( cornerCount );
766         for (i = 0; i < cornerCount; i++)
767         {
768           double x = subPictureLeft + corners[i].x;
769           double y = subPictureTop  - corners[i].y;
770           double z =  0;
771         
772           aGeomCorner = aBasicOperations->MakePointXYZ( x,y,z );
773         
774           geomCorners[i] = aGeomCorner;  
775         } 
776         GEOM::GEOM_Object_var aCompound = aShapesOperations->MakeCompound(geomCorners);    
777         if ( !aCompound->_is_nil() )
778         {
779           // Dark blue color
780           SALOMEDS::Color aColor;
781           aColor.R = 0;
782           aColor.G = 0;
783           aColor.B = 0.8;
784
785           aCompound->SetColor(aColor);
786           aCompound->SetMarkerStd(GEOM::MT_POINT,GEOM::MS_30);
787           objects.push_back( aCompound._retn() );
788           res = true;
789         }
790       }   
791     }
792     else if (myConstructorId == CONTOURS)
793     {    
794       GEOM::GEOM_ICurvesOperations_var aCurveOperations = myGeomGUI->GetGeomGen()->GetICurvesOperations( getStudyId() );
795
796       myDetector->ComputeContours( useROI, parameters );
797       std::vector< std::vector<cv::Point> >   contours  = myDetector->GetContours();
798       std::vector<cv::Vec4i>                  hierarchy = myDetector->GetContoursHierarchy();
799     
800       std::vector< cv::Point >                contour;
801       int idx = 0;
802       
803       GEOM::ListOfGO_var                      geomContours = new GEOM::ListOfGO();
804       int contourCount = 0;
805     
806       bool insert;
807     
808       MESSAGE("hierarchy.size() =" << hierarchy.size()) 
809       if ( hierarchy.size() < 1 ) {
810         getOperation()->SetErrorCode( "Impossible detected contours" );
811         return false;
812       }
813
814       for( ; idx >= 0; idx = hierarchy[idx][0])
815       {
816 //       for(int count=0, child=idx; child>=0, count<1; child=hierarchy[idx][2], count++)
817 //       {     
818 //         contour = contours[child];
819         contour = contours[idx];
820         std::vector< cv::Point >::iterator it;
821         std::vector< cv::Point >::iterator it_previous;
822         std::vector< cv::Point >::iterator it_next;
823         GEOM::GEOM_Object_var  aGeomContourPnt;
824         GEOM::ListOfGO_var     geomContourPnts = new GEOM::ListOfGO();
825        
826         geomContourPnts->length( contour.size() );
827
828         int j = 0;
829         std::set< std::vector<int> > existing_points;
830         std::pair< std::set< std::vector<int> >::iterator,bool > pnt_it;
831         for ( it=contour.begin() ; it < contour.end()-1; it++ )
832         {
833           int pnt_array[] = {it->x,it->y};     
834           std::vector<int> pnt (pnt_array, pnt_array + sizeof(pnt_array) / sizeof(int) );
835
836           pnt_it=existing_points.insert(pnt);
837           if (pnt_it.second == true)         // To avoid double points in the contours
838           {
839             insert = true;
840             if (it!=contour.begin())         // From the second point on perform some checking to avoid loops in the contours we build
841             {
842               it_previous = boost::prior(it);
843               it_next = boost::next(it);
844               
845               double u_v_scalar_product = (it->x - it_previous->x) * (it_next->x - it->x) + 
846                                           (it->y - it_previous->y) * (it_next->y - it->y);                                       
847               if (u_v_scalar_product < 0)
848               {
849                 double u_v_det = (it->x - it_previous->x) * (it_next->y - it->y) - 
850                                  (it->y - it_previous->y) * (it_next->x - it->x);
851                                           
852                 double norme_u = sqrt ( double(it->x - it_previous->x) * double(it->x - it_previous->x) +
853                                         double(it->y - it_previous->y) * double(it->y - it_previous->y) );
854                 
855                 double norme_v = sqrt ( double(it->x - it_next->x) * double(it->x - it_next->x) +
856                                         double(it->y - it_next->y) * double(it->y - it_next->y) );
857                                                                                                 
858                 double u_v_sinus = u_v_det / (norme_u * norme_v);
859                 
860                 if (fabs(u_v_sinus) < Precision::Confusion())
861                 { 
862                   insert = false;
863                 }                         
864               }
865             }
866             double x = -0.5 *width  + it->x;
867             double y =  0.5 *height - it->y;
868             double z =  0;
869             if (insert)
870             {
871               aGeomContourPnt    = aBasicOperations->MakePointXYZ( x,y,z );
872               geomContourPnts->length( j+1 );
873               geomContourPnts[j] = aGeomContourPnt;
874               j++;
875             }
876           }
877         }
878         
879         GEOM::GEOM_Object_var aWire;
880         if(myOutputGroup->RadioButton2->isChecked())
881         {
882           aWire = aCurveOperations->MakePolyline(geomContourPnts.in(), false);
883         }
884         else if(myOutputGroup->RadioButton1->isChecked())
885         {
886           aWire = aCurveOperations->MakeSplineInterpolation(geomContourPnts.in(), /*closed =*/ false, /*reordering =*/ false);
887         }
888         else
889           return res;
890         
891         if ( !aWire->_is_nil() )
892         {
893           geomContours->length(contourCount + 1);
894           geomContours[contourCount] = aWire;
895           contourCount++;
896         }
897 //       }
898       }
899       GEOM::GEOM_Object_var aContoursCompound = aShapesOperations->MakeCompound(geomContours);
900       if ( !aContoursCompound->_is_nil() )
901       {
902         objects.push_back( aContoursCompound._retn() );
903       }
904       res=true;
905     }
906   }
907   catch( ... ) {
908     getOperation()->SetErrorCode( "Impossible detected contours/corners" );
909     return false;
910   }
911   
912   // TEST not very conclusive
913   
914 //   else if(myConstructorId ==LINES)
915 //   {
916 //     myDetector->ComputeLines();
917 //     std::vector<cv::Vec4i>  lines = myDetector->GetLines();
918 //     GEOM::GEOM_Object_var  Pnt1;
919 //     GEOM::GEOM_Object_var  Pnt2;
920 //     GEOM::GEOM_Object_var  aLine;
921 //     
922 //     GEOM::ListOfGO_var     geomLines = new GEOM::ListOfGO();
923 //     int linesCount=0;
924 //     for( int i = 0; i < lines.size(); i++ )
925 //     {
926 //       Pnt1 = aBasicOperations->MakePointXYZ( -0.5 *width + lines[i][0], 0.5 *height - lines[i][1], 0 );
927 //       Pnt2 = aBasicOperations->MakePointXYZ( -0.5 *width + lines[i][2], 0.5 *height - lines[i][3], 0 );
928 //       aLine = aBasicOperations->MakeLineTwoPnt( Pnt1, Pnt2 );
929 //       if ( !aLine->_is_nil() )
930 //       {
931 //         geomLines->length(linesCount + 1);
932 //         geomLines[linesCount] = aLine;
933 //         linesCount++;
934 //       }
935 //     }
936 //     GEOM::GEOM_Object_var aLinesCompound = aShapesOperations->MakeCompound(geomLines);
937 //     if ( !aLinesCompound->_is_nil() )
938 //     {
939 //       objects.push_back( aLinesCompound._retn() );
940 //     }
941 // 
942 //     res=true;
943 //   }
944   
945   return res;
946 }
947
948 //=================================================================================
949 // function : getSourceObjects
950 // purpose  : virtual method to get source objects
951 //=================================================================================
952 QList<GEOM::GeomObjPtr> EntityGUI_FeatureDetectorDlg::getSourceObjects()
953 {
954   QList<GEOM::GeomObjPtr> res;
955   res << myFace;
956   return res;
957 }