1 #include "Translate.h"
2
3 #include "Application.h"
4
5 #include <Standard_WarningsDisable.hxx>
6 #include <QDir>
7 #include <QLayout>
8 #include <QComboBox>
9 #include <QGroupBox>
10 #include <QList>
11 #include <QListView>
12 #include <QFileDialog>
13 #include <QApplication>
14 #include <QWidget>
15 #include <QStyleFactory>
16 #include <Standard_WarningsRestore.hxx>
17
18 #include <AIS_Shape.hxx>
19 #include <AIS_InteractiveObject.hxx>
20
21 #include <IGESControl_Reader.hxx>
22 #include <IGESControl_Writer.hxx>
23 #include <IGESControl_Controller.hxx>
24 #include <STEPControl_Reader.hxx>
25 #include <STEPControl_Writer.hxx>
26 #include <STEPControl_StepModelType.hxx>
27 #include <Interface_Static.hxx>
28 //#include <Interface_TraceFile.hxx>
29
30 #include <StlAPI_Writer.hxx>
31 #include <VrmlAPI_Writer.hxx>
32
33 #include <BRepTools.hxx>
34 #include <BRep_Tool.hxx>
35 #include <BRep_Builder.hxx>
36
37 #include <TopoDS.hxx>
38 #include <TopoDS_Shape.hxx>
39 #include <TopoDS_Compound.hxx>
40 #include <TopExp_Explorer.hxx>
41 #include <TopTools_HSequenceOfShape.hxx>
42
43 #include <Geom_Line.hxx>
44 #include <Geom_Curve.hxx>
45 #include <Geom_Plane.hxx>
46 #include <Geom_Surface.hxx>
47
48
49 #include <Standard_ErrorHandler.hxx>
50 #include <Standard_CString.hxx>
51
52 // ---------------------------- TranslateDlg -----------------------------------------
53
54 class TranslateDlg : public QFileDialog
55 {
56 public:
57 TranslateDlg( QWidget* = 0, Qt::WindowFlags flags = 0, bool = true );
58 ~TranslateDlg();
59 int getMode() const;
60 void setMode( const int );
61 void addMode( const int, const QString& );
62 void clear();
63
64 protected:
65 void showEvent ( QShowEvent* event );
66
67 private:
68 QListView* findListView( const QObjectList& );
69
70 private:
71 QComboBox* myBox;
72 QList<int> myList;
73 };
74
TranslateDlg(QWidget * parent,Qt::WindowFlags flags,bool modal)75 TranslateDlg::TranslateDlg( QWidget* parent, Qt::WindowFlags flags, bool modal )
76 : QFileDialog( parent, flags )
77 {
78 setOption( QFileDialog::DontUseNativeDialog );
79 setModal( modal );
80
81 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
82
83 if( grid )
84 {
85 QVBoxLayout *vbox = new QVBoxLayout;
86
87 QWidget* paramGroup = new QWidget( this );
88 paramGroup->setLayout( vbox );
89
90 myBox = new QComboBox( paramGroup );
91 vbox->addWidget( myBox );
92
93 int row = grid->rowCount();
94 grid->addWidget( paramGroup, row, 1, 1, 3 ); // make combobox occupy 1 row and 3 columns starting from 1
95 }
96 }
97
~TranslateDlg()98 TranslateDlg::~TranslateDlg()
99 {
100 }
101
getMode() const102 int TranslateDlg::getMode() const
103 {
104 if ( myBox->currentIndex() < 0 || myBox->currentIndex() > (int)myList.count() - 1 )
105 return -1;
106 else
107 return myList.at( myBox->currentIndex() );
108 }
109
setMode(const int mode)110 void TranslateDlg::setMode( const int mode )
111 {
112 int idx = myList.indexOf( mode );
113 if ( idx >= 0 )
114 myBox->setCurrentIndex( idx );
115 }
116
addMode(const int mode,const QString & name)117 void TranslateDlg::addMode( const int mode, const QString& name )
118 {
119 myBox->show();
120 myBox->addItem( name );
121 myList.append( mode );
122 myBox->updateGeometry();
123 updateGeometry();
124 }
125
clear()126 void TranslateDlg::clear()
127 {
128 myList.clear();
129 myBox->clear();
130 myBox->hide();
131 myBox->updateGeometry();
132 updateGeometry();
133 }
134
findListView(const QObjectList & childList)135 QListView* TranslateDlg::findListView( const QObjectList & childList )
136 {
137 QListView* listView = 0;
138 for ( int i = 0, n = childList.count(); i < n && !listView; i++ )
139 {
140 listView = qobject_cast<QListView*>( childList.at( i ) );
141 if ( !listView && childList.at( i ) )
142 {
143 listView = findListView( childList.at( i )->children() );
144 }
145 }
146 return listView;
147 }
148
showEvent(QShowEvent * event)149 void TranslateDlg::showEvent ( QShowEvent* event )
150 {
151 QFileDialog::showEvent ( event );
152 QListView* aListView = findListView( children() );
153 aListView->setViewMode( QListView::ListMode );
154 }
155
156
157 // ---------------------------- Translate -----------------------------------------
158
Translate(QObject * parent)159 Translate::Translate( QObject* parent )
160 : QObject( parent ),
161 myDlg( 0 )
162 {
163 }
164
~Translate()165 Translate::~Translate()
166 {
167 if ( myDlg )
168 delete myDlg;
169 }
170
info() const171 QString Translate::info() const
172 {
173 return myInfo;
174 }
175
importModel(const int format,const Handle (AIS_InteractiveContext)& ic)176 bool Translate::importModel( const int format, const Handle(AIS_InteractiveContext)& ic )
177 {
178 myInfo = QString();
179 QString fileName = selectFileName( format, true );
180 if ( fileName.isEmpty() )
181 return true;
182
183 if ( !QFileInfo( fileName ).exists() )
184 {
185 myInfo = QObject::tr( "INF_TRANSLATE_FILENOTFOUND" ).arg( fileName );
186 return false;
187 }
188
189 QApplication::setOverrideCursor( Qt::WaitCursor );
190 Handle(TopTools_HSequenceOfShape) shapes = importModel( format, fileName );
191 QApplication::restoreOverrideCursor();
192
193 return displayShSequence(ic, shapes);
194 }
195
displayShSequence(const Handle (AIS_InteractiveContext)& ic,const Handle (TopTools_HSequenceOfShape)& shapes)196 bool Translate::displayShSequence(const Handle(AIS_InteractiveContext)& ic,
197 const Handle(TopTools_HSequenceOfShape)& shapes )
198 {
199 if ( shapes.IsNull() || !shapes->Length() )
200 return false;
201
202 for ( int i = 1; i <= shapes->Length(); i++ )
203 ic->Display( new AIS_Shape( shapes->Value( i ) ), false );
204 ic->UpdateCurrentViewer();
205 return true;
206 }
207
Handle(TopTools_HSequenceOfShape)208 Handle(TopTools_HSequenceOfShape) Translate::importModel( const int format, const QString& file )
209 {
210 Handle(TopTools_HSequenceOfShape) shapes;
211 try {
212 switch ( format )
213 {
214 case FormatBREP:
215 shapes = importBREP( file );
216 break;
217 case FormatIGES:
218 shapes = importIGES( file );
219 break;
220 case FormatSTEP:
221 shapes = importSTEP( file );
222 break;
223 }
224 } catch ( Standard_Failure ) {
225 shapes.Nullify();
226 }
227 return shapes;
228 }
229
exportModel(const int format,const Handle (AIS_InteractiveContext)& ic)230 bool Translate::exportModel( const int format, const Handle(AIS_InteractiveContext)& ic )
231 {
232 myInfo = QString();
233 QString fileName = selectFileName( format, false );
234 if ( fileName.isEmpty() )
235 return true;
236
237 Handle(TopTools_HSequenceOfShape) shapes = getShapes( ic );
238 if ( shapes.IsNull() || !shapes->Length() )
239 return false;
240
241 QApplication::setOverrideCursor( Qt::WaitCursor );
242 bool stat = exportModel( format, fileName, shapes );
243 QApplication::restoreOverrideCursor();
244
245 return stat;
246 }
247
exportModel(const int format,const QString & file,const Handle (TopTools_HSequenceOfShape)& shapes)248 bool Translate::exportModel( const int format, const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
249 {
250 try {
251 switch ( format )
252 {
253 case FormatBREP: return exportBREP( file, shapes );
254 case FormatIGES: return exportIGES( file, shapes );
255 case FormatSTEP: return exportSTEP( file, shapes );
256 case FormatSTL: return exportSTL ( file, shapes );
257 case FormatVRML: return exportVRML( file, shapes );
258 }
259 } catch ( Standard_Failure ) {
260 //
261 }
262 return false;
263 }
264
Handle(TopTools_HSequenceOfShape)265 Handle(TopTools_HSequenceOfShape) Translate::getShapes( const Handle(AIS_InteractiveContext)& ic )
266 {
267 Handle(TopTools_HSequenceOfShape) aSequence;
268 Handle(AIS_InteractiveObject) picked;
269 for ( ic->InitSelected(); ic->MoreSelected(); ic->NextSelected() )
270 {
271 Handle(AIS_InteractiveObject) obj = ic->SelectedInteractive();
272 if ( obj->IsKind( STANDARD_TYPE( AIS_Shape ) ) )
273 {
274 TopoDS_Shape shape = Handle(AIS_Shape)::DownCast(obj)->Shape();
275 if ( aSequence.IsNull() )
276 aSequence = new TopTools_HSequenceOfShape();
277 aSequence->Append( shape );
278 }
279 }
280 return aSequence;
281 }
282
283 /*!
284 Selects a file from standard dialog according to selection 'filter'
285 */
selectFileName(const int format,const bool import)286 QString Translate::selectFileName( const int format, const bool import )
287 {
288 TranslateDlg* theDlg = getDialog( format, import );
289
290 int ret = theDlg->exec();
291
292 qApp->processEvents();
293
294 QString file;
295 QStringList fileNames;
296 if ( ret != QDialog::Accepted )
297 return file;
298
299 fileNames = theDlg->selectedFiles();
300 if (!fileNames.isEmpty())
301 file = fileNames[0];
302
303 if ( !QFileInfo( file ).completeSuffix().length() )
304 {
305 QString selFilter = theDlg->selectedNameFilter();
306 int idx = selFilter.indexOf( "(*." );
307 if ( idx != -1 )
308 {
309 QString tail = selFilter.mid( idx + 3 );
310 idx = tail.indexOf( " " );
311 if ( idx == -1 )
312 idx = tail.indexOf( ")" );
313 QString ext = tail.left( idx );
314 if ( ext.length() )
315 file += QString( "." ) + ext;
316 }
317 }
318
319 return file;
320 }
321
getDialog(const int format,const bool import)322 TranslateDlg* Translate::getDialog( const int format, const bool import )
323 {
324 if ( !myDlg )
325 myDlg = new TranslateDlg( 0, 0, true );
326
327 if ( format < 0 )
328 return myDlg;
329
330 QString formatFilter = QObject::tr( QString( "INF_FILTER_FORMAT_%1" ).arg( format ).toLatin1().constData() );
331 QString allFilter = QObject::tr( "INF_FILTER_FORMAT_ALL" );
332
333 QString filter;
334 filter.append( formatFilter );
335 filter.append( "\t" );
336
337 if ( import )
338 {
339 filter.append( allFilter );
340 filter.append( "\t" );
341 }
342
343 std::cout << filter.toLatin1().constData() << std::endl;
344 QStringList filters = filter.split( "\t" );
345 myDlg->setNameFilters ( filters );
346
347 if ( import )
348 {
349 myDlg->setWindowTitle( QObject::tr( "INF_APP_IMPORT" ) );
350 ((QFileDialog*)myDlg)->setFileMode( QFileDialog::ExistingFile );
351 }
352 else
353 {
354 myDlg->setWindowTitle( QObject::tr( "INF_APP_EXPORT" ) );
355 ((QFileDialog*)myDlg)->setFileMode( QFileDialog::AnyFile );
356 }
357
358 myDlg->clear();
359
360 if ( !import )
361 {
362 switch ( format )
363 {
364 case FormatSTEP:
365 myDlg->addMode( STEPControl_ManifoldSolidBrep, QObject::tr( "INF_BREP_MOIFOLD" ) );
366 myDlg->addMode( STEPControl_FacetedBrep, QObject::tr( "INF_BREP_FACETED" ) );
367 myDlg->addMode( STEPControl_ShellBasedSurfaceModel, QObject::tr( "INF_BREP_SHELL" ) );
368 myDlg->addMode( STEPControl_GeometricCurveSet, QObject::tr( "INF_BREP_CURVE" ) );
369 break;
370 }
371 }
372
373 return myDlg;
374 }
375
376 // ----------------------------- Import functionality -----------------------------
377
Handle(TopTools_HSequenceOfShape)378 Handle(TopTools_HSequenceOfShape) Translate::importBREP( const QString& file )
379 {
380 Handle(TopTools_HSequenceOfShape) aSequence;
381 TopoDS_Shape aShape;
382 BRep_Builder aBuilder;
383 TCollection_AsciiString aFilePath = file.toUtf8().data();
384 Standard_Boolean result = BRepTools::Read( aShape, aFilePath.ToCString(), aBuilder );
385 if ( result )
386 {
387 aSequence = new TopTools_HSequenceOfShape();
388 aSequence->Append( aShape );
389 }
390 return aSequence;
391 }
392
Handle(TopTools_HSequenceOfShape)393 Handle(TopTools_HSequenceOfShape) Translate::importIGES( const QString& file )
394 {
395 Handle(TopTools_HSequenceOfShape) aSequence;
396 TCollection_AsciiString aFilePath = file.toUtf8().data();
397
398 IGESControl_Reader Reader;
399 int status = Reader.ReadFile(aFilePath.ToCString() );
400
401 if ( status == IFSelect_RetDone )
402 {
403 aSequence = new TopTools_HSequenceOfShape();
404 Reader.TransferRoots();
405 TopoDS_Shape aShape = Reader.OneShape();
406 aSequence->Append( aShape );
407 }
408 return aSequence;
409 }
410
Handle(TopTools_HSequenceOfShape)411 Handle(TopTools_HSequenceOfShape) Translate::importSTEP( const QString& file )
412 {
413 Handle(TopTools_HSequenceOfShape) aSequence = new TopTools_HSequenceOfShape;
414 TCollection_AsciiString aFilePath = file.toUtf8().data();
415 STEPControl_Reader aReader;
416 IFSelect_ReturnStatus status = aReader.ReadFile( aFilePath.ToCString() );
417 if ( status != IFSelect_RetDone )
418 {
419 return aSequence;
420 }
421
422 //Interface_TraceFile::SetDefault();
423 bool failsonly = false;
424 aReader.PrintCheckLoad( failsonly, IFSelect_ItemsByEntity );
425
426 int nbr = aReader.NbRootsForTransfer();
427 aReader.PrintCheckTransfer( failsonly, IFSelect_ItemsByEntity );
428 for ( Standard_Integer n = 1; n <= nbr; n++ )
429 {
430 aReader.TransferRoot( n );
431 }
432
433 int nbs = aReader.NbShapes();
434 if ( nbs > 0 )
435 {
436 for ( int i = 1; i <= nbs; i++ )
437 {
438 TopoDS_Shape shape = aReader.Shape( i );
439 aSequence->Append( shape );
440 }
441 }
442
443 return aSequence;
444 }
445
446 // ----------------------------- Export functionality -----------------------------
447
exportBREP(const QString & file,const Handle (TopTools_HSequenceOfShape)& shapes)448 bool Translate::exportBREP( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
449 {
450 if ( shapes.IsNull() || shapes->IsEmpty() )
451 return false;
452
453 TopoDS_Shape shape = shapes->Value( 1 );
454
455 const TCollection_AsciiString anUtf8Path (file.toUtf8().data());
456
457 return BRepTools::Write( shape, anUtf8Path.ToCString() );
458 }
459
exportIGES(const QString & file,const Handle (TopTools_HSequenceOfShape)& shapes)460 bool Translate::exportIGES( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
461 {
462 if ( shapes.IsNull() || shapes->IsEmpty() )
463 return false;
464
465 IGESControl_Controller::Init();
466 IGESControl_Writer writer( Interface_Static::CVal( "XSTEP.iges.unit" ),
467 Interface_Static::IVal( "XSTEP.iges.writebrep.mode" ) );
468
469 for ( int i = 1; i <= shapes->Length(); i++ )
470 writer.AddShape ( shapes->Value( i ) );
471 writer.ComputeModel();
472
473 const TCollection_AsciiString anUtf8Path (file.toUtf8().data());
474
475 return writer.Write( anUtf8Path.ToCString() );
476 }
477
exportSTEP(const QString & file,const Handle (TopTools_HSequenceOfShape)& shapes)478 bool Translate::exportSTEP( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
479 {
480 if ( shapes.IsNull() || shapes->IsEmpty() )
481 return false;
482
483 TranslateDlg* theDlg = getDialog( -1, false );
484 STEPControl_StepModelType type = (STEPControl_StepModelType)theDlg->getMode();
485 if ( type < 0 )
486 return false;
487
488 IFSelect_ReturnStatus status;
489
490 if ( type == STEPControl_FacetedBrep && !checkFacetedBrep( shapes ) )
491 {
492 myInfo = QObject::tr( "INF_FACET_ERROR" );
493 return false;
494 }
495
496 STEPControl_Writer writer;
497 for ( int i = 1; i <= shapes->Length(); i++ )
498 {
499 status = writer.Transfer( shapes->Value( i ), type );
500 if ( status != IFSelect_RetDone )
501 return false;
502 }
503
504 const TCollection_AsciiString anUtf8Path (file.toUtf8().data());
505
506 status = writer.Write( anUtf8Path.ToCString() );
507
508 switch ( status )
509 {
510 case IFSelect_RetError:
511 myInfo = QObject::tr( "INF_DATA_ERROR" );
512 break;
513 case IFSelect_RetFail:
514 myInfo = QObject::tr( "INF_WRITING_ERROR" );
515 break;
516 case IFSelect_RetVoid:
517 myInfo = QObject::tr( "INF_NOTHING_ERROR" );
518 break;
519 case IFSelect_RetStop:
520 case IFSelect_RetDone:
521 break;
522 }
523 return status == IFSelect_RetDone;
524 }
525
exportSTL(const QString & file,const Handle (TopTools_HSequenceOfShape)& shapes)526 bool Translate::exportSTL( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
527 {
528 if ( shapes.IsNull() || shapes->IsEmpty() )
529 return false;
530
531 TopoDS_Compound res;
532 BRep_Builder builder;
533 builder.MakeCompound( res );
534
535 for ( int i = 1; i <= shapes->Length(); i++ )
536 {
537 TopoDS_Shape shape = shapes->Value( i );
538 if ( shape.IsNull() )
539 {
540 myInfo = QObject::tr( "INF_TRANSLATE_ERROR_INVALIDSHAPE" );
541 return false;
542 }
543 builder.Add( res, shape );
544 }
545
546 StlAPI_Writer writer;
547
548 const TCollection_AsciiString anUtf8Path (file.toUtf8().data());
549
550 writer.Write( res, anUtf8Path.ToCString() );
551
552 return true;
553 }
554
exportVRML(const QString & file,const Handle (TopTools_HSequenceOfShape)& shapes)555 bool Translate::exportVRML( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
556 {
557 if ( shapes.IsNull() || shapes->IsEmpty() )
558 return false;
559
560 TopoDS_Compound res;
561 BRep_Builder builder;
562 builder.MakeCompound( res );
563
564 for ( int i = 1; i <= shapes->Length(); i++ )
565 {
566 TopoDS_Shape shape = shapes->Value( i );
567 if ( shape.IsNull() )
568 {
569 myInfo = QObject::tr( "INF_TRANSLATE_ERROR_INVALIDSHAPE" );
570 return false;
571 }
572 builder.Add( res, shape );
573 }
574
575 VrmlAPI_Writer writer;
576
577 const TCollection_AsciiString anUtf8Path (file.toUtf8().data());
578
579 writer.Write( res, anUtf8Path.ToCString() );
580
581 return true;
582 }
583
checkFacetedBrep(const Handle (TopTools_HSequenceOfShape)& shapes)584 bool Translate::checkFacetedBrep( const Handle(TopTools_HSequenceOfShape)& shapes )
585 {
586 bool err = false;
587 for ( int i = 1; i <= shapes->Length(); i++ )
588 {
589 TopoDS_Shape shape = shapes->Value( i );
590 for ( TopExp_Explorer fexp( shape, TopAbs_FACE ); fexp.More() && !err; fexp.Next() )
591 {
592 Handle(Geom_Surface) surface = BRep_Tool::Surface( TopoDS::Face( fexp.Current() ) );
593 if ( !surface->IsKind( STANDARD_TYPE( Geom_Plane ) ) )
594 err = true;
595 }
596 for ( TopExp_Explorer eexp( shape, TopAbs_EDGE ); eexp.More() && !err; eexp.Next() )
597 {
598 Standard_Real fd, ld;
599 Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge( eexp.Current() ), fd, ld );
600 if ( !curve->IsKind( STANDARD_TYPE( Geom_Line ) ) )
601 err = true;
602 }
603 }
604 return !err;
605 }
606
607
608
609