Salome HOME
tools refactoring on two parts (OCCT/QT and other products dependencies)
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_RecognizeContoursOp.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include "HYDROGUI_RecognizeContoursOp.h"
20
21 #include "HYDROGUI_RecognizeContoursDlg.h"
22 #include "HYDROGUI_Module.h"
23 #include "HYDROGUI_Shape.h"
24 #include "HYDROGUI_Tool2.h"
25 #include "HYDROGUI_UpdateFlags.h"
26 #include "HYDROGUI_OCCSelector.h"
27 #include "HYDROGUI_ZLayers.h"
28
29 #include <HYDROData_Document.h>
30 #include <HYDROData_GeomTool.h>
31 #include <HYDROData_ShapesTool.h>
32 #include <HYDROData_PolylineXY.h>
33
34 #include <GeometryGUI.h>
35 #include <GeometryGUI_Operations.h>
36 #include <GEOM_Constants.h>
37 #include <GEOMBase.h>
38
39 #include <OCCViewer_ViewManager.h>
40 #include <OCCViewer_ViewModel.h>
41
42 #include <SalomeApp_Study.h>
43
44 #include <LightApp_Application.h>
45 #include <LightApp_DataOwner.h>
46 #include <LightApp_Displayer.h>
47 #include <LightApp_SelectionMgr.h>
48
49 #include <SUIT_Desktop.h>
50 #include <SUIT_ViewManager.h>
51
52 #include <BRepBuilderAPI_GTransform.hxx>
53 #include <gp_GTrsf.hxx>
54
55 #include <QDialog>
56 #include <QDir>
57 #include <QTemporaryFile>
58
59 /**
60   Constructor.
61 */
62 HYDROGUI_RecognizeContoursOp::HYDROGUI_RecognizeContoursOp( HYDROGUI_Module* theModule )
63 : HYDROGUI_Operation( theModule ),
64   myGEOMOpName( "" )
65 {
66   setName( tr( "CONTOURS_RECOGNITION" ) );
67 }
68
69 /**
70   Destructor.
71 */
72 HYDROGUI_RecognizeContoursOp::~HYDROGUI_RecognizeContoursOp()
73 {
74   cleanup();
75 }
76
77 /**
78 */
79 void HYDROGUI_RecognizeContoursOp::startOperation()
80 {
81   HYDROGUI_Operation::startOperation();
82   
83   // Set preview view manager
84   if ( !getPreviewManager() ) {
85     setPreviewManager( ::qobject_cast<OCCViewer_ViewManager*>( 
86                        module()->getApp()->getViewManager( OCCViewer_Viewer::Type(), true ) ) );
87   }
88
89   if ( !isApplyAndClose() ) {
90     return;
91   }
92
93   // Get the selected image
94   myImage = Handle(HYDROData_Image)::DownCast( HYDROGUI_Tool::GetSelectedObject( module() ) );
95   if ( myImage.IsNull() ) {
96     abort();
97     return;
98   }
99   QString anImageName = myImage->GetName();
100
101   // Create temporary graphics file
102   QImage aQImage = myImage->Image();
103   myTmpImageFile = new QTemporaryFile( QDir::tempPath() + QDir::separator() + anImageName );
104   if ( !myTmpImageFile->open() || 
105        !aQImage.save( myTmpImageFile->fileName(), "PNG", 100 ) ) {
106     abort();
107     return;
108   }
109
110   // Create the input panel
111   HYDROGUI_RecognizeContoursDlg* aPanel = 
112     ::qobject_cast<HYDROGUI_RecognizeContoursDlg*>( inputPanel() );
113   if ( !aPanel ) {
114     return;
115   }
116
117   // Reset the panel
118   aPanel->reset();
119   aPanel->setImageName( anImageName );
120
121   // Get active study
122   SalomeApp_Study* aStudy = 
123     dynamic_cast<SalomeApp_Study*>( module()->getApp()->activeStudy() );
124
125   // Get active view manager
126   SUIT_ViewManager* aViewMgr = module()->getApp()->activeViewManager();
127
128   // Export the selected image to GEOM module
129   if ( aStudy && aViewMgr ) {
130     SALOMEDS::Study_var aDSStudy = GeometryGUI::ClientStudyToStudy( aStudy->studyDS() );
131     GEOM::GEOM_Gen_var aGeomEngine = GeometryGUI::GetGeomGen();
132
133     QString aGeomPictureEntry;
134
135     HYDROData_GeomTool::createFaceInGEOM( aGeomEngine, aDSStudy, aQImage.width(), aQImage.height(), 
136                                           anImageName, aGeomPictureEntry );
137     
138     if ( !aGeomPictureEntry.isEmpty() ) {
139       aStudy->setObjectProperty( aViewMgr->getGlobalId(), aGeomPictureEntry, 
140                                  GEOM::propertyName( GEOM::Texture ), myTmpImageFile->fileName() );
141     
142       // update the object browser
143       module()->getApp()->updateObjectBrowser( true );
144
145       // browse the published GEOM picture
146       QStringList anEntries;
147       anEntries << aGeomPictureEntry;
148       browseObjects( anEntries );
149
150       // Add GEOM picture object entry to the list of temporary geom objects
151       myTmpGeomObjects << aGeomPictureEntry;
152     }
153   }
154
155   // Activate GEOM module operation
156   LightApp_Application* anApp = module()->getApp();
157   if ( anApp ) {
158     connect( anApp, SIGNAL( operationFinished( const QString&, const QString&, const QStringList& ) ), 
159              this, SLOT( onExternalOperationFinished( const QString&, const QString&, const QStringList& ) ) );
160
161     module()->getApp()->activateOperation( "Geometry", GEOMOp::OpFeatureDetect );
162   }
163 }
164
165 /**
166 */
167 void HYDROGUI_RecognizeContoursOp::abortOperation()
168 {
169   LightApp_Application* anApp = module()->getApp();
170   if ( anApp ) {
171     anApp->disconnect( this );
172   }
173
174   cleanup();
175
176   HYDROGUI_Operation::abortOperation();
177 }
178
179 /**
180 */
181 void HYDROGUI_RecognizeContoursOp::commitOperation()
182 {
183   if ( isApplyAndClose() ) {
184     cleanup();
185   }
186
187   HYDROGUI_Operation::commitOperation();
188 }
189
190 /**
191 */
192 bool HYDROGUI_RecognizeContoursOp::processApply( int& theUpdateFlags,
193                                                 QString& theErrorMsg,
194                                                 QStringList& theBrowseObjectsEntries )
195 {
196   // Check the original image
197   if ( myImage.IsNull() ) {
198     return false;
199   }
200
201   // Get panel
202   HYDROGUI_RecognizeContoursDlg* aPanel = 
203     ::qobject_cast<HYDROGUI_RecognizeContoursDlg*>( inputPanel() );
204   if ( !aPanel ) {
205     return false;
206   }
207   
208   // Check if contour GEOM object exists
209   if ( myGeomContourEntry.isEmpty() ) {
210     theErrorMsg = tr( "NO_DETECTED_CONTOURS" );
211     return false;
212   }
213
214   // Get selected polylines
215   QStringList aSelectedtPolylines = aPanel->getSelectedtPolylineNames();
216   // Remove the selected polylines from the panel
217   aPanel->removePolylineNames( aSelectedtPolylines );
218
219   // Create polylines
220   foreach ( QString aName, aSelectedtPolylines ) {
221     TopoDS_Shape aShape = myPolylineShapes.value( aName )->getTopoShape();
222     if ( aShape.IsNull() ) {
223       continue;
224     }
225
226     Handle(HYDROData_PolylineXY) aPolylineObj =
227       Handle(HYDROData_PolylineXY)::DownCast( doc()->CreateObject( KIND_POLYLINEXY ) );
228
229     if( !aPolylineObj.IsNull() ) {
230       aPolylineObj->SetName( aName );
231       aPolylineObj->ImportShape( aShape );
232       aPolylineObj->SetWireColor( HYDROData_PolylineXY::DefaultWireColor() );
233
234       aPolylineObj->Update();
235       module()->setIsToUpdate( aPolylineObj );
236     }
237
238     // Remove the shape from the map
239     HYDROGUI_Shape* aShapeToDelete = myPolylineShapes.take( aName );
240     delete aShapeToDelete;
241   }
242  
243   theUpdateFlags = UF_Model;
244
245   return true;
246 }
247
248 /**
249 */
250 HYDROGUI_InputPanel* HYDROGUI_RecognizeContoursOp::createInputPanel() const
251 {
252   HYDROGUI_InputPanel* aPanel = new HYDROGUI_RecognizeContoursDlg( module(), getName() );
253
254   connect( aPanel, SIGNAL( selectionChanged( const QStringList& ) ), this, SLOT( onSelectionChanged( const QStringList& ) ) );
255
256   return aPanel;
257 }
258
259 /**
260  * Called when the operation perfomed by another module is finished.
261  * \param theModuleName the name of the module which perfomed the operation
262  * \param theOperationName the operation name
263  * \param theEntryList the list of the created objects entries
264  */
265 void HYDROGUI_RecognizeContoursOp::onExternalOperationFinished( 
266   const QString& theModuleName, const QString& theOperationName,
267   const QStringList& theEntryList )
268 {
269   // Process "Geometry" module operations only
270   if ( theModuleName != "Geometry" ) {
271     return;
272   }
273     
274   // Store the operation name
275   myGEOMOpName = theOperationName;
276
277   // Close the dialog corresponding to the external operation
278   closeExternalOperationDlg();
279   
280   // Erase the GEOM objects
281   LightApp_Displayer().Erase( theEntryList );
282
283   // Add GEOM object entries to the list of temporary GEOM objects
284   myTmpGeomObjects << theEntryList;
285
286   if ( theEntryList.count() == 1 ) {
287     myGeomContourEntry = theEntryList.first();
288
289     // Update the list of polylines
290     updateRecognizedPolylines();
291   }
292 }
293
294 /**
295   Close the GEOM contours detection dialog.
296 */
297 void HYDROGUI_RecognizeContoursOp::closeExternalOperationDlg()
298 {
299   if ( myGEOMOpName.isEmpty() ) {
300     return;
301   }
302
303   SUIT_Desktop* aDesktop = module()->getApp()->desktop();
304   if ( aDesktop ) {
305     QList<QDialog*> aDialogs = aDesktop->findChildren<QDialog*>();
306     foreach ( QDialog* aDlg, aDialogs ) {
307       if ( typeid(*aDlg).name() == myGEOMOpName ) {
308         aDlg->close();
309         break;
310       }
311     }
312   }
313 }
314
315 /**
316   Update the list of recognized polylines by exploding the GEOM contour object.
317 */
318 void HYDROGUI_RecognizeContoursOp::updateRecognizedPolylines()
319 {
320   // Erase the preview
321   erasePreview();
322
323   // Get active study
324   SalomeApp_Study* aStudy = 
325     dynamic_cast<SalomeApp_Study*>( module()->getApp()->activeStudy() );
326   if ( !aStudy ) {
327     return;
328   }
329
330   // Explode the compound
331   _PTR(SObject) aSObject( aStudy->studyDS()->FindObjectID( qPrintable( myGeomContourEntry ) ) );
332   if ( aSObject ) {
333     TopoDS_Shape aShape = GEOMBase::GetShapeFromIOR( aSObject->GetIOR().c_str() );
334
335     TopTools_SequenceOfShape aSubShapes;
336     HYDROData_ShapesTool::ExploreShapeToShapes( aShape, TopAbs_WIRE, aSubShapes );
337     if ( aSubShapes.Length() < 1 ) {
338       HYDROData_ShapesTool::ExploreShapeToShapes( aShape, TopAbs_EDGE, aSubShapes );
339     }
340
341     Handle(AIS_InteractiveContext) aCtx = NULL;
342
343     // Display preview
344     OCCViewer_ViewManager* aViewManager = getPreviewManager();
345     if ( aViewManager ) {
346       if ( OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer() ) {
347         // aViewer->enablePreselection( true );
348         // aViewer->enableSelection( true );
349         aCtx = aViewer->getAISContext();
350         connect( aViewer, SIGNAL( selectionChanged() ), this, SLOT( onViewerSelectionChanged() ) );
351       }
352     }
353
354     QTransform aTrsf = myImage->Trsf();
355     QImage anImage = myImage->Image();
356     QRectF aRect( QPointF( 0, 0 ), QPointF( anImage.width(), anImage.height() ) );
357     aRect = aTrsf.mapRect( aRect );
358     aTrsf.setMatrix( aTrsf.m11(), aTrsf.m12(),  aTrsf.m13(),
359                      aTrsf.m21(), -aTrsf.m22(), aTrsf.m23(),
360                      aTrsf.m31() + aRect.width() * 0.5, aTrsf.m32 () - aRect.height() * 0.5, aTrsf.m33() );
361
362     /*
363     QTransform aTrsf = myImage->Trsf();
364     gp_Mat aMat( aTrsf.m11(), aTrsf.m21(), 0, 
365                  aTrsf.m12(), -aTrsf.m22(), 0, 
366                  0,           0,           1 );
367     QImage anImage = myImage->Image();
368     QRectF aRect( QPointF( 0, 0 ), QPointF( anImage.width(), anImage.height() ) );
369     aRect = aTrsf.mapRect( aRect );
370     gp_XYZ aVec( aTrsf.m31() + aRect.width() * 0.5, 
371                  aTrsf.m32() - aRect.height() * 0.5, 0 );
372
373     BRepBuilderAPI_GTransform aBuilder( gp_GTrsf( aMat, aVec ) );
374     */
375
376     Handle(HYDROData_PolylineXY) aPolylineObj = Handle(HYDROData_PolylineXY)::DownCast( doc()->CreateObject( KIND_POLYLINEXY ) );
377     QStringList aNamesList;
378     for ( int i = 1; i <= aSubShapes.Length(); i++ ) {
379       TopoDS_Shape aSubShape = aSubShapes.Value( i );
380
381       // Transform the sub-shape
382       aPolylineObj->ImportShape( aSubShape );
383       aPolylineObj->Transform( aTrsf );
384
385       /*
386       aBuilder.Perform( aSubShape, Standard_True );
387       if ( aBuilder.IsDone() ) {
388         aSubShape = aBuilder.Shape();
389       }*/
390       
391       HYDROGUI_Shape* aShape = new HYDROGUI_Shape( aCtx, NULL, getPreviewZLayer() );
392       aShape->setShape( aPolylineObj->GetShape(), true, false );
393       aShape->setBorderColor( HYDROData_PolylineXY::DefaultWireColor(), false, false );
394       
395       QString aPrefix = QString("%1_%2_%3").arg( myImage->GetName(), "Contour", QString::number( i ) );
396       QString aName = HYDROGUI_Tool::GenerateObjectName( module(), aPrefix, QStringList(), true );
397       myPolylineShapes.insert( aName, aShape);
398       aNamesList << aName;
399     }
400
401     aPolylineObj->Remove();
402
403     if ( !aCtx.IsNull() ) {
404       UpdateZLayersOfHilightPresentationsOfDisplayedObjects( aCtx, Graphic3d_ZLayerId_TopOSD );
405       aCtx->UpdateCurrentViewer();
406     }
407
408     // Get panel
409     HYDROGUI_RecognizeContoursDlg* aPanel = 
410       ::qobject_cast<HYDROGUI_RecognizeContoursDlg*>( inputPanel() );
411     if ( aPanel ) {
412       aPanel->setPolylineNames( aNamesList );
413     }
414   }
415 }
416
417 /**
418   Erase the preview.
419 */
420 void HYDROGUI_RecognizeContoursOp::erasePreview()
421 {
422   foreach ( HYDROGUI_Shape* aShape, myPolylineShapes ) {
423     delete aShape;
424   }
425
426   myPolylineShapes.clear();
427 }
428
429 /**
430   Called when selection of the recognized polylines is changed.
431 */
432 void HYDROGUI_RecognizeContoursOp::onSelectionChanged( const QStringList& theSelectedNames )
433 {
434   Handle(AIS_InteractiveContext) aCtx = NULL;
435
436   OCCViewer_ViewManager* aViewManager = getPreviewManager();
437   if ( aViewManager ) {
438     if ( OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer() ) {
439       aCtx = aViewer->getAISContext();
440     }
441   }
442
443   if ( !aCtx.IsNull() ) {
444     foreach ( QString aName, myPolylineShapes.keys() ) {
445       Handle(AIS_InteractiveObject) anObject = 
446         myPolylineShapes.value(aName)->getAISObject();
447
448       bool isSelected = theSelectedNames.contains( aName );
449       if ( ( isSelected && !aCtx->IsSelected( anObject) ) ||
450            ( !isSelected && aCtx->IsSelected( anObject) ) ) {
451         aCtx->AddOrRemoveSelected( anObject, Standard_False );
452       }
453       // myPolylineShapes[aName]->highlight( isSelected, true );
454     }
455     aCtx->UpdateCurrentViewer();
456   }
457 }
458
459 /**
460   Called when selection in the viewer is changed.
461 */
462 void HYDROGUI_RecognizeContoursOp::onViewerSelectionChanged()
463 {
464   // Get panel
465   HYDROGUI_RecognizeContoursDlg* aPanel = 
466     ::qobject_cast<HYDROGUI_RecognizeContoursDlg*>( inputPanel() );
467   if ( !aPanel ) {
468     return;
469   }
470
471
472   OCCViewer_ViewManager* aViewManager = getPreviewManager();
473   Handle(AIS_InteractiveContext) aCtx = NULL;
474   if ( aViewManager ) {
475     if ( OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer() ) {
476       aCtx = aViewer->getAISContext();
477     }
478   }
479   
480   if ( !aCtx.IsNull() ) {
481     QStringList aSelectedNames;
482
483     foreach ( QString aName, myPolylineShapes.keys() ) {
484       bool isSelected = aCtx->IsSelected( myPolylineShapes.value(aName)->getAISObject() );
485       if ( isSelected ) {
486         aSelectedNames << aName;
487       }
488     }
489
490     aPanel->setSelectedPolylineNames( aSelectedNames );
491   }
492 }
493
494 /**
495   Do the operation data cleanup.
496 */
497 void HYDROGUI_RecognizeContoursOp::cleanup()
498 {
499   // Close the external operation dialog
500   closeExternalOperationDlg();
501
502   // Erase the preview 
503   erasePreview();
504
505   // Delete temporary image file
506   if ( myTmpImageFile ) {
507     delete myTmpImageFile;
508     myTmpImageFile = NULL;
509   }
510
511   // Delete temporary GEOM objects
512   if ( !myTmpGeomObjects.isEmpty() ) {
513     HYDROGUI_Tool::DeleteGeomObjects( module(), myTmpGeomObjects );
514     // update the object browser
515     module()->getApp()->updateObjectBrowser( true );
516   }
517 }