7fd59977 |
1 | #include "Translate.h" |
2 | |
3 | #include "Application.h" |
4 | |
5 | #include <QDir> |
6 | #include <QLayout> |
7 | #include <QComboBox> |
8 | #include <QGroupBox> |
9 | #include <QList> |
10 | #include <QListView> |
11 | #include <QFileDialog> |
12 | #include <QApplication> |
13 | #include <QWidget> |
861a7b03 |
14 | #include <QStyleFactory> |
7fd59977 |
15 | |
16 | #include <AIS_Shape.hxx> |
17 | #include <AIS_InteractiveObject.hxx> |
18 | |
19 | #include <FSD_File.hxx> |
20 | |
7fd59977 |
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 | |
7fd59977 |
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 | |
75 | TranslateDlg::TranslateDlg( QWidget* parent, Qt::WindowFlags flags, bool modal ) |
76 | : QFileDialog( parent, flags ) |
77 | { |
861a7b03 |
78 | setOption( QFileDialog::DontUseNativeDialog ); |
7fd59977 |
79 | setModal( modal ); |
861a7b03 |
80 | |
7fd59977 |
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 | |
98 | TranslateDlg::~TranslateDlg() |
99 | { |
100 | } |
101 | |
102 | 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 | |
110 | void TranslateDlg::setMode( const int mode ) |
111 | { |
112 | int idx = myList.indexOf( mode ); |
113 | if ( idx >= 0 ) |
114 | myBox->setCurrentIndex( idx ); |
115 | } |
116 | |
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 | |
126 | void TranslateDlg::clear() |
127 | { |
128 | myList.clear(); |
129 | myBox->clear(); |
130 | myBox->hide(); |
131 | myBox->updateGeometry(); |
132 | updateGeometry(); |
133 | } |
134 | |
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 | |
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 | |
159 | Translate::Translate( QObject* parent ) |
160 | : QObject( parent ), |
161 | myDlg( 0 ) |
162 | { |
163 | } |
164 | |
165 | Translate::~Translate() |
166 | { |
167 | if ( myDlg ) |
168 | delete myDlg; |
169 | } |
170 | |
171 | QString Translate::info() const |
172 | { |
173 | return myInfo; |
174 | } |
175 | |
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 | |
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 | |
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; |
7fd59977 |
223 | } |
224 | } catch ( Standard_Failure ) { |
225 | shapes.Nullify(); |
226 | } |
227 | return shapes; |
228 | } |
229 | |
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 | |
248 | bool Translate::exportModel( const int format, const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes ) |
249 | { |
250 | bool status; |
251 | try { |
252 | switch ( format ) |
253 | { |
254 | case FormatBREP: |
255 | status = exportBREP( file, shapes ); |
256 | break; |
257 | case FormatIGES: |
258 | status = exportIGES( file, shapes ); |
259 | break; |
260 | case FormatSTEP: |
261 | status = exportSTEP( file, shapes ); |
262 | break; |
7fd59977 |
263 | case FormatSTL: |
264 | status = exportSTL( file, shapes ); |
265 | break; |
266 | case FormatVRML: |
267 | status = exportVRML( file, shapes ); |
268 | break; |
269 | } |
270 | } catch ( Standard_Failure ) { |
271 | status = false; |
272 | } |
273 | return status; |
274 | } |
275 | |
276 | Handle(TopTools_HSequenceOfShape) Translate::getShapes( const Handle(AIS_InteractiveContext)& ic ) |
277 | { |
278 | Handle(TopTools_HSequenceOfShape) aSequence; |
279 | Handle(AIS_InteractiveObject) picked; |
280 | for ( ic->InitCurrent(); ic->MoreCurrent(); ic->NextCurrent() ) |
281 | { |
282 | Handle(AIS_InteractiveObject) obj = ic->Current(); |
283 | if ( obj->IsKind( STANDARD_TYPE( AIS_Shape ) ) ) |
284 | { |
285 | TopoDS_Shape shape = Handle(AIS_Shape)::DownCast(obj)->Shape(); |
286 | if ( aSequence.IsNull() ) |
287 | aSequence = new TopTools_HSequenceOfShape(); |
288 | aSequence->Append( shape ); |
289 | } |
290 | } |
291 | return aSequence; |
292 | } |
293 | |
294 | /*! |
295 | Selects a file from standard dialog acoording to selection 'filter' |
296 | */ |
297 | QString Translate::selectFileName( const int format, const bool import ) |
298 | { |
299 | TranslateDlg* theDlg = getDialog( format, import ); |
300 | |
301 | int ret = theDlg->exec(); |
302 | |
303 | qApp->processEvents(); |
304 | |
305 | QString file; |
306 | QStringList fileNames; |
307 | if ( ret != QDialog::Accepted ) |
308 | return file; |
309 | |
310 | fileNames = theDlg->selectedFiles(); |
311 | if (!fileNames.isEmpty()) |
312 | file = fileNames[0]; |
313 | |
314 | if ( !QFileInfo( file ).completeSuffix().length() ) |
315 | { |
861a7b03 |
316 | QString selFilter = theDlg->selectedNameFilter(); |
7fd59977 |
317 | int idx = selFilter.indexOf( "(*." ); |
318 | if ( idx != -1 ) |
319 | { |
320 | QString tail = selFilter.mid( idx + 3 ); |
321 | int idx = tail.indexOf( " " ); |
322 | if ( idx == -1 ) |
323 | idx = tail.indexOf( ")" ); |
324 | QString ext = tail.left( idx ); |
325 | if ( ext.length() ) |
326 | file += QString( "." ) + ext; |
327 | } |
328 | } |
329 | |
330 | return file; |
331 | } |
332 | |
333 | TranslateDlg* Translate::getDialog( const int format, const bool import ) |
334 | { |
335 | if ( !myDlg ) |
336 | myDlg = new TranslateDlg( 0, 0, true ); |
337 | |
338 | if ( format < 0 ) |
339 | return myDlg; |
340 | |
341 | QString formatFilter = QObject::tr( QString( "INF_FILTER_FORMAT_%1" ).arg( format ).toLatin1().constData() ); |
342 | QString allFilter = QObject::tr( "INF_FILTER_FORMAT_ALL" ); |
343 | |
344 | QString filter; |
345 | filter.append( formatFilter ); |
346 | filter.append( "\t" ); |
347 | |
348 | if ( import ) |
349 | { |
350 | filter.append( allFilter ); |
351 | filter.append( "\t" ); |
352 | } |
353 | |
354 | cout << filter.toLatin1().constData() << endl; |
355 | QStringList filters = filter.split( "\t" ); |
861a7b03 |
356 | myDlg->setNameFilters ( filters ); |
7fd59977 |
357 | |
358 | if ( import ) |
359 | { |
360 | myDlg->setWindowTitle( QObject::tr( "INF_APP_IMPORT" ) ); |
361 | ((QFileDialog*)myDlg)->setFileMode( QFileDialog::ExistingFile ); |
362 | } |
363 | else |
364 | { |
365 | myDlg->setWindowTitle( QObject::tr( "INF_APP_EXPORT" ) ); |
366 | ((QFileDialog*)myDlg)->setFileMode( QFileDialog::AnyFile ); |
367 | } |
368 | |
861a7b03 |
369 | QString datadir = (QString (qgetenv ("CASROOT").constData()) + QObject::tr( QString("INF_PATH_%1").arg( format ).toLatin1().constData() ) ); |
7fd59977 |
370 | |
371 | myDlg->clear(); |
372 | |
373 | if ( !import ) |
374 | { |
375 | switch ( format ) |
376 | { |
377 | case FormatSTEP: |
378 | myDlg->addMode( STEPControl_ManifoldSolidBrep, QObject::tr( "INF_BREP_MOIFOLD" ) ); |
379 | myDlg->addMode( STEPControl_FacetedBrep, QObject::tr( "INF_BREP_FACETED" ) ); |
380 | myDlg->addMode( STEPControl_ShellBasedSurfaceModel, QObject::tr( "INF_BREP_SHELL" ) ); |
381 | myDlg->addMode( STEPControl_GeometricCurveSet, QObject::tr( "INF_BREP_CURVE" ) ); |
382 | break; |
7fd59977 |
383 | } |
384 | } |
385 | |
386 | return myDlg; |
387 | } |
388 | |
389 | // ----------------------------- Import functionality ----------------------------- |
390 | |
391 | Handle(TopTools_HSequenceOfShape) Translate::importBREP( const QString& file ) |
392 | { |
393 | Handle(TopTools_HSequenceOfShape) aSequence; |
394 | TopoDS_Shape aShape; |
395 | BRep_Builder aBuilder; |
90c8c7f3 |
396 | TCollection_AsciiString aFilePath = file.toUtf8().data(); |
397 | Standard_Boolean result = BRepTools::Read( aShape, aFilePath.ToCString(), aBuilder ); |
7fd59977 |
398 | if ( result ) |
399 | { |
400 | aSequence = new TopTools_HSequenceOfShape(); |
401 | aSequence->Append( aShape ); |
402 | } |
403 | return aSequence; |
404 | } |
405 | |
406 | Handle(TopTools_HSequenceOfShape) Translate::importIGES( const QString& file ) |
407 | { |
408 | Handle(TopTools_HSequenceOfShape) aSequence; |
90c8c7f3 |
409 | TCollection_AsciiString aFilePath = file.toUtf8().data(); |
410 | |
7fd59977 |
411 | IGESControl_Reader Reader; |
90c8c7f3 |
412 | int status = Reader.ReadFile(aFilePath.ToCString() ); |
7fd59977 |
413 | |
414 | if ( status == IFSelect_RetDone ) |
415 | { |
416 | aSequence = new TopTools_HSequenceOfShape(); |
417 | Reader.TransferRoots(); |
418 | TopoDS_Shape aShape = Reader.OneShape(); |
419 | aSequence->Append( aShape ); |
420 | } |
421 | return aSequence; |
422 | } |
423 | |
424 | Handle(TopTools_HSequenceOfShape) Translate::importSTEP( const QString& file ) |
425 | { |
426 | Handle(TopTools_HSequenceOfShape) aSequence; |
90c8c7f3 |
427 | TCollection_AsciiString aFilePath = file.toUtf8().data(); |
7fd59977 |
428 | STEPControl_Reader aReader; |
90c8c7f3 |
429 | IFSelect_ReturnStatus status = aReader.ReadFile( aFilePath.ToCString() ); |
7fd59977 |
430 | if ( status == IFSelect_RetDone ) |
431 | { |
432 | //Interface_TraceFile::SetDefault(); |
433 | bool failsonly = false; |
434 | aReader.PrintCheckLoad( failsonly, IFSelect_ItemsByEntity ); |
435 | |
436 | int nbr = aReader.NbRootsForTransfer(); |
437 | aReader.PrintCheckTransfer( failsonly, IFSelect_ItemsByEntity ); |
438 | for ( Standard_Integer n = 1; n <= nbr; n++ ) |
439 | { |
440 | bool ok = aReader.TransferRoot( n ); |
441 | int nbs = aReader.NbShapes(); |
861a7b03 |
442 | if ( ok == true && nbs > 0 ) |
7fd59977 |
443 | { |
444 | aSequence = new TopTools_HSequenceOfShape(); |
445 | for ( int i = 1; i <= nbs; i++ ) |
446 | { |
447 | TopoDS_Shape shape = aReader.Shape( i ); |
448 | aSequence->Append( shape ); |
449 | } |
450 | } |
451 | } |
452 | } |
453 | return aSequence; |
454 | } |
455 | |
7fd59977 |
456 | // ----------------------------- Export functionality ----------------------------- |
457 | |
458 | bool Translate::exportBREP( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes ) |
459 | { |
460 | if ( shapes.IsNull() || shapes->IsEmpty() ) |
461 | return false; |
462 | |
463 | TopoDS_Shape shape = shapes->Value( 1 ); |
464 | return BRepTools::Write( shape, (Standard_CString)file.toLatin1().constData() ); |
465 | } |
466 | |
467 | bool Translate::exportIGES( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes ) |
468 | { |
469 | if ( shapes.IsNull() || shapes->IsEmpty() ) |
470 | return false; |
471 | |
472 | IGESControl_Controller::Init(); |
473 | IGESControl_Writer writer( Interface_Static::CVal( "XSTEP.iges.unit" ), |
474 | Interface_Static::IVal( "XSTEP.iges.writebrep.mode" ) ); |
475 | |
476 | for ( int i = 1; i <= shapes->Length(); i++ ) |
477 | writer.AddShape ( shapes->Value( i ) ); |
478 | writer.ComputeModel(); |
479 | return writer.Write( (Standard_CString)file.toLatin1().constData() ); |
480 | } |
481 | |
482 | bool Translate::exportSTEP( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes ) |
483 | { |
484 | if ( shapes.IsNull() || shapes->IsEmpty() ) |
485 | return false; |
486 | |
487 | TranslateDlg* theDlg = getDialog( -1, false ); |
488 | STEPControl_StepModelType type = (STEPControl_StepModelType)theDlg->getMode(); |
489 | if ( type < 0 ) |
490 | return false; |
491 | |
492 | IFSelect_ReturnStatus status; |
493 | |
494 | if ( type == STEPControl_FacetedBrep && !checkFacetedBrep( shapes ) ) |
495 | { |
496 | myInfo = QObject::tr( "INF_FACET_ERROR" ); |
497 | return false; |
498 | } |
499 | |
500 | STEPControl_Writer writer; |
501 | for ( int i = 1; i <= shapes->Length(); i++ ) |
502 | { |
503 | status = writer.Transfer( shapes->Value( i ), type ); |
504 | if ( status != IFSelect_RetDone ) |
505 | return false; |
506 | } |
507 | |
508 | status = writer.Write( (Standard_CString)file.toLatin1().constData() ); |
509 | |
510 | switch ( status ) |
511 | { |
512 | case IFSelect_RetError: |
513 | myInfo = QObject::tr( "INF_DATA_ERROR" ); |
514 | break; |
515 | case IFSelect_RetFail: |
516 | myInfo = QObject::tr( "INF_WRITING_ERROR" ); |
517 | break; |
518 | case IFSelect_RetVoid: |
519 | myInfo = QObject::tr( "INF_NOTHING_ERROR" ); |
520 | break; |
521 | } |
522 | return status == IFSelect_RetDone; |
523 | } |
524 | |
7fd59977 |
525 | bool Translate::exportSTL( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes ) |
526 | { |
527 | if ( shapes.IsNull() || shapes->IsEmpty() ) |
528 | return false; |
529 | |
530 | TopoDS_Compound res; |
531 | BRep_Builder builder; |
532 | builder.MakeCompound( res ); |
533 | |
534 | for ( int i = 1; i <= shapes->Length(); i++ ) |
535 | { |
536 | TopoDS_Shape shape = shapes->Value( i ); |
537 | if ( shape.IsNull() ) |
538 | { |
539 | myInfo = QObject::tr( "INF_TRANSLATE_ERROR_INVALIDSHAPE" ); |
540 | return false; |
541 | } |
542 | builder.Add( res, shape ); |
543 | } |
544 | |
545 | StlAPI_Writer writer; |
546 | writer.Write( res, (Standard_CString)file.toLatin1().constData() ); |
547 | |
548 | return true; |
549 | } |
550 | |
551 | bool Translate::exportVRML( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes ) |
552 | { |
553 | if ( shapes.IsNull() || shapes->IsEmpty() ) |
554 | return false; |
555 | |
556 | TopoDS_Compound res; |
557 | BRep_Builder builder; |
558 | builder.MakeCompound( res ); |
559 | |
560 | for ( int i = 1; i <= shapes->Length(); i++ ) |
561 | { |
562 | TopoDS_Shape shape = shapes->Value( i ); |
563 | if ( shape.IsNull() ) |
564 | { |
565 | myInfo = QObject::tr( "INF_TRANSLATE_ERROR_INVALIDSHAPE" ); |
566 | return false; |
567 | } |
568 | builder.Add( res, shape ); |
569 | } |
570 | |
571 | VrmlAPI_Writer writer; |
572 | writer.Write( res, (Standard_CString)file.toLatin1().constData() ); |
573 | |
574 | return true; |
575 | } |
576 | |
577 | bool Translate::checkFacetedBrep( const Handle(TopTools_HSequenceOfShape)& shapes ) |
578 | { |
579 | bool err = false; |
580 | for ( int i = 1; i <= shapes->Length(); i++ ) |
581 | { |
582 | TopoDS_Shape shape = shapes->Value( i ); |
583 | for ( TopExp_Explorer fexp( shape, TopAbs_FACE ); fexp.More() && !err; fexp.Next() ) |
584 | { |
585 | Handle(Geom_Surface) surface = BRep_Tool::Surface( TopoDS::Face( fexp.Current() ) ); |
586 | if ( !surface->IsKind( STANDARD_TYPE( Geom_Plane ) ) ) |
587 | err = true; |
588 | } |
589 | for ( TopExp_Explorer eexp( shape, TopAbs_EDGE ); eexp.More() && !err; eexp.Next() ) |
590 | { |
591 | Standard_Real fd, ld; |
592 | Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge( eexp.Current() ), fd, ld ); |
593 | if ( !curve->IsKind( STANDARD_TYPE( Geom_Line ) ) ) |
594 | err = true; |
595 | } |
596 | } |
597 | return !err; |
598 | } |
599 | |
600 | |
601 | |