0032527: Data Exchange, RWGltf_CafWriter - make name format configurable
[occt.git] / src / XSDRAWSTLVRML / XSDRAWSTLVRML.cxx
1 // Created on: 2000-05-30
2 // Created by: Sergey MOZOKHIN
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <AIS_InteractiveContext.hxx>
18 #include <Aspect_TypeOfMarker.hxx>
19 #include <Bnd_Box.hxx>
20 #include <BRep_Builder.hxx>
21 #include <DBRep.hxx>
22 #include <DDocStd.hxx>
23 #include <DDocStd_DrawDocument.hxx>
24 #include <Draw.hxx>
25 #include <Draw_Interpretor.hxx>
26 #include <Draw_PluginMacro.hxx>
27 #include <Draw_ProgressIndicator.hxx>
28 #include <Graphic3d_MaterialAspect.hxx>
29 #include <MeshVS_DataMapOfIntegerAsciiString.hxx>
30 #include <MeshVS_DeformedDataSource.hxx>
31 #include <MeshVS_Drawer.hxx>
32 #include <MeshVS_DrawerAttribute.hxx>
33 #include <MeshVS_ElementalColorPrsBuilder.hxx>
34 #include <MeshVS_Mesh.hxx>
35 #include <MeshVS_MeshEntityOwner.hxx>
36 #include <MeshVS_MeshPrsBuilder.hxx>
37 #include <MeshVS_NodalColorPrsBuilder.hxx>
38 #include <MeshVS_PrsBuilder.hxx>
39 #include <MeshVS_TextPrsBuilder.hxx>
40 #include <MeshVS_VectorPrsBuilder.hxx>
41 #include <OSD_Path.hxx>
42 #include <Quantity_Color.hxx>
43 #include <Quantity_HArray1OfColor.hxx>
44 #include <Quantity_NameOfColor.hxx>
45 #include <RWGltf_CafReader.hxx>
46 #include <RWGltf_CafWriter.hxx>
47 #include <RWStl.hxx>
48 #include <RWObj.hxx>
49 #include <RWObj_CafReader.hxx>
50 #include <RWObj_CafWriter.hxx>
51 #include <SelectMgr_SelectionManager.hxx>
52 #include <Standard_ErrorHandler.hxx>
53 #include <StdSelect_ViewerSelector3d.hxx>
54 #include <StlAPI.hxx>
55 #include <StlAPI_Writer.hxx>
56 #include <TColgp_SequenceOfXYZ.hxx>
57 #include <TCollection_AsciiString.hxx>
58 #include <TColStd_Array1OfReal.hxx>
59 #include <TColStd_HPackedMapOfInteger.hxx>
60 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
61 #include <TDataStd_Name.hxx>
62 #include <TDocStd_Application.hxx>
63 #include <TDocStd_Document.hxx>
64 #include <TopoDS_Face.hxx>
65 #include <TopoDS_Shape.hxx>
66 #include <UnitsAPI.hxx>
67 #include <UnitsMethods.hxx>
68 #include <V3d_View.hxx>
69 #include <ViewerTest.hxx>
70 #include <VrmlAPI.hxx>
71 #include <VrmlAPI_Writer.hxx>
72 #include <VrmlData_DataMapOfShapeAppearance.hxx>
73 #include <VrmlData_Scene.hxx>
74 #include <VrmlData_ShapeConvert.hxx>
75 #include <XCAFDoc_DocumentTool.hxx>
76 #include <XCAFDoc_ShapeTool.hxx>
77 #include <XSDRAW.hxx>
78 #include <XSDRAWIGES.hxx>
79 #include <XSDRAWSTEP.hxx>
80 #include <XSDRAWSTLVRML.hxx>
81 #include <XSDRAWSTLVRML_DataSource.hxx>
82 #include <XSDRAWSTLVRML_DataSource3D.hxx>
83 #include <XSDRAWSTLVRML_DrawableMesh.hxx>
84
85 #ifndef _STDIO_H
86 #include <stdio.h>
87 #endif
88
89 extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
90                                            const Handle(AIS_InteractiveObject)& theAISObj,
91                                            Standard_Boolean theReplaceIfExists = Standard_True);
92
93 //! Parse RWMesh_NameFormat enumeration.
94 static bool parseNameFormat (const char* theArg,
95                              RWMesh_NameFormat& theFormat)
96 {
97   TCollection_AsciiString aName (theArg);
98   aName.LowerCase();
99   if (aName == "empty")
100   {
101     theFormat = RWMesh_NameFormat_Empty;
102   }
103   else if (aName == "product"
104         || aName == "prod")
105   {
106     theFormat = RWMesh_NameFormat_Product;
107   }
108   else if (aName == "instance"
109         || aName == "inst")
110   {
111     theFormat = RWMesh_NameFormat_Instance;
112   }
113   else if (aName == "instanceorproduct"
114         || aName == "instance||product"
115         || aName == "instance|product"
116         || aName == "instorprod"
117         || aName == "inst||prod"
118         || aName == "inst|prod")
119   {
120     theFormat = RWMesh_NameFormat_InstanceOrProduct;
121   }
122   else if (aName == "productorinstance"
123         || aName == "product||instance"
124         || aName == "product|instance"
125         || aName == "prodorinst"
126         || aName == "prod||inst"
127         || aName == "prod|inst")
128   {
129     theFormat = RWMesh_NameFormat_ProductOrInstance;
130   }
131   else if (aName == "productandinstance"
132         || aName == "prodandinst"
133         || aName == "product&instance"
134         || aName == "prod&inst")
135   {
136     theFormat = RWMesh_NameFormat_ProductAndInstance;
137   }
138   else if (aName == "productandinstanceandocaf"
139         || aName == "verbose"
140         || aName == "debug")
141   {
142     theFormat = RWMesh_NameFormat_ProductAndInstanceAndOcaf;
143   }
144   else
145   {
146     return false;
147   }
148   return true;
149 }
150
151 //=============================================================================
152 //function : ReadGltf
153 //purpose  : Reads glTF file
154 //=============================================================================
155 static Standard_Integer ReadGltf (Draw_Interpretor& theDI,
156                                   Standard_Integer theNbArgs,
157                                   const char** theArgVec)
158 {
159   TCollection_AsciiString aDestName, aFilePath;
160   Standard_Boolean toUseExistingDoc = Standard_False;
161   Standard_Real aSystemUnitFactor = UnitsMethods::GetCasCadeLengthUnit() * 0.001;
162   Standard_Boolean toListExternalFiles = Standard_False;
163   Standard_Boolean isParallel = Standard_False;
164   Standard_Boolean isDoublePrec = Standard_False;
165   Standard_Boolean toSkipLateDataLoading = Standard_False;
166   Standard_Boolean toKeepLateData = Standard_True;
167   Standard_Boolean toPrintDebugInfo = Standard_False;
168   Standard_Boolean isNoDoc = (TCollection_AsciiString(theArgVec[0]) == "readgltf");
169   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
170   {
171     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
172     anArgCase.LowerCase();
173     if (!isNoDoc
174      && (anArgCase == "-nocreate"
175       || anArgCase == "-nocreatedoc"))
176     {
177       toUseExistingDoc = Standard_True;
178       if (anArgIter + 1 < theNbArgs
179        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toUseExistingDoc))
180       {
181         ++anArgIter;
182       }
183     }
184     else if (anArgCase == "-parallel")
185     {
186       isParallel = Standard_True;
187       if (anArgIter + 1 < theNbArgs
188        && Draw::ParseOnOff (theArgVec[anArgIter + 1], isParallel))
189       {
190         ++anArgIter;
191       }
192     }
193     else if (anArgCase == "-doubleprec"
194           || anArgCase == "-doubleprecision"
195           || anArgCase == "-singleprec"
196           || anArgCase == "-singleprecision")
197     {
198       isDoublePrec = Standard_True;
199       if (anArgIter + 1 < theNbArgs
200        && Draw::ParseOnOff (theArgVec[anArgIter + 1], isDoublePrec))
201       {
202         ++anArgIter;
203       }
204       if (anArgCase.StartsWith ("-single"))
205       {
206         isDoublePrec = !isDoublePrec;
207       }
208     }
209     else if (anArgCase == "-skiplateloading")
210     {
211       toSkipLateDataLoading = Standard_True;
212       if (anArgIter + 1 < theNbArgs
213        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toSkipLateDataLoading))
214       {
215         ++anArgIter;
216       }
217     }
218     else if (anArgCase == "-keeplate")
219     {
220       toKeepLateData = Standard_True;
221       if (anArgIter + 1 < theNbArgs
222        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toKeepLateData))
223       {
224         ++anArgIter;
225       }
226     }
227     else if (anArgCase == "-toprintinfo"
228           || anArgCase == "-toprintdebuginfo")
229     {
230       toPrintDebugInfo = Standard_True;
231       if (anArgIter + 1 < theNbArgs
232        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toPrintDebugInfo))
233       {
234         ++anArgIter;
235       }
236     }
237     else if (anArgCase == "-listexternalfiles"
238           || anArgCase == "-listexternals"
239           || anArgCase == "-listexternal"
240           || anArgCase == "-external"
241           || anArgCase == "-externalfiles")
242     {
243       toListExternalFiles = Standard_True;
244     }
245     else if (aDestName.IsEmpty())
246     {
247       aDestName = theArgVec[anArgIter];
248     }
249     else if (aFilePath.IsEmpty())
250     {
251       aFilePath = theArgVec[anArgIter];
252     }
253     else
254     {
255       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
256       return 1;
257     }
258   }
259   if (aFilePath.IsEmpty())
260   {
261     Message::SendFail() << "Syntax error: wrong number of arguments";
262     return 1;
263   }
264
265   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
266   Handle(TDocStd_Document) aDoc;
267   if (!toListExternalFiles
268    && !isNoDoc)
269   {
270     Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
271     Standard_CString aNameVar = aDestName.ToCString();
272     DDocStd::GetDocument (aNameVar, aDoc, Standard_False);
273     if (aDoc.IsNull())
274     {
275       if (toUseExistingDoc)
276       {
277         Message::SendFail() << "Error: document with name " << aDestName << " does not exist";
278         return 1;
279       }
280       anApp->NewDocument (TCollection_ExtendedString ("BinXCAF"), aDoc);
281     }
282     else if (!toUseExistingDoc)
283     {
284       Message::SendFail() << "Error: document with name " << aDestName << " already exists";
285       return 1;
286     }
287   }
288
289   RWGltf_CafReader aReader;
290   aReader.SetSystemLengthUnit (aSystemUnitFactor);
291   aReader.SetSystemCoordinateSystem (RWMesh_CoordinateSystem_Zup);
292   aReader.SetDocument (aDoc);
293   aReader.SetParallel (isParallel);
294   aReader.SetDoublePrecision (isDoublePrec);
295   aReader.SetToSkipLateDataLoading (toSkipLateDataLoading);
296   aReader.SetToKeepLateData (toKeepLateData);
297   aReader.SetToPrintDebugMessages (toPrintDebugInfo);
298   if (toListExternalFiles)
299   {
300     aReader.ProbeHeader (aFilePath);
301     for (NCollection_IndexedMap<TCollection_AsciiString>::Iterator aFileIter (aReader.ExternalFiles()); aFileIter.More(); aFileIter.Next())
302     {
303       theDI << "\"" << aFileIter.Value() << "\" ";
304     }
305   }
306   else
307   {
308     aReader.Perform (aFilePath, aProgress->Start());
309     if (isNoDoc)
310     {
311       DBRep::Set (aDestName.ToCString(), aReader.SingleShape());
312     }
313     else
314     {
315       Handle(DDocStd_DrawDocument) aDrawDoc = new DDocStd_DrawDocument (aDoc);
316       TDataStd_Name::Set (aDoc->GetData()->Root(), aDestName);
317       Draw::Set (aDestName.ToCString(), aDrawDoc);
318     }
319   }
320   return 0;
321 }
322
323 //=============================================================================
324 //function : WriteGltf
325 //purpose  : Writes glTF file
326 //=============================================================================
327 static Standard_Integer WriteGltf (Draw_Interpretor& theDI,
328                                    Standard_Integer theNbArgs,
329                                    const char** theArgVec)
330 {
331   TCollection_AsciiString aGltfFilePath;
332   Handle(TDocStd_Document) aDoc;
333   Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
334   TColStd_IndexedDataMapOfStringString aFileInfo;
335   RWGltf_WriterTrsfFormat aTrsfFormat = RWGltf_WriterTrsfFormat_Compact;
336   bool toForceUVExport = false, toEmbedTexturesInGlb = true;
337   RWMesh_NameFormat aNodeNameFormat = RWMesh_NameFormat_InstanceOrProduct;
338   RWMesh_NameFormat aMeshNameFormat = RWMesh_NameFormat_Product;
339   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
340   {
341     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
342     anArgCase.LowerCase();
343     if (anArgCase == "-comments"
344      && anArgIter + 1 < theNbArgs)
345     {
346       aFileInfo.Add ("Comments", theArgVec[++anArgIter]);
347     }
348     else if (anArgCase == "-author"
349           && anArgIter + 1 < theNbArgs)
350     {
351       aFileInfo.Add ("Author", theArgVec[++anArgIter]);
352     }
353     else if (anArgCase == "-forceuvexport"
354           || anArgCase == "-forceuv")
355     {
356       toForceUVExport = true;
357       if (anArgIter + 1 < theNbArgs
358        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toForceUVExport))
359       {
360         ++anArgIter;
361       }
362     }
363     else if (anArgCase == "-trsfformat"
364           && anArgIter + 1 < theNbArgs)
365     {
366       TCollection_AsciiString aTrsfStr (theArgVec[++anArgIter]);
367       aTrsfStr.LowerCase();
368       if (aTrsfStr == "compact")
369       {
370         aTrsfFormat = RWGltf_WriterTrsfFormat_Compact;
371       }
372       else if (aTrsfStr == "mat4")
373       {
374         aTrsfFormat = RWGltf_WriterTrsfFormat_Mat4;
375       }
376       else if (aTrsfStr == "trs")
377       {
378         aTrsfFormat = RWGltf_WriterTrsfFormat_TRS;
379       }
380       else
381       {
382         Message::SendFail() << "Syntax error at '" << anArgCase << "'";
383         return 1;
384       }
385     }
386     else if (anArgCase == "-nodenameformat"
387           || anArgCase == "-nodename")
388     {
389       ++anArgIter;
390       if (anArgIter >= theNbArgs
391       || !parseNameFormat (theArgVec[anArgIter], aNodeNameFormat))
392       {
393         Message::SendFail() << "Syntax error at '" << anArgCase << "'";
394         return 1;
395       }
396     }
397     else if (anArgCase == "-meshnameformat"
398           || anArgCase == "-meshname")
399     {
400       ++anArgIter;
401       if (anArgIter >= theNbArgs
402       || !parseNameFormat (theArgVec[anArgIter], aMeshNameFormat))
403       {
404         Message::SendFail() << "Syntax error at '" << anArgCase << "'";
405         return 1;
406       }
407     }
408     else if (aDoc.IsNull())
409     {
410       Standard_CString aNameVar = theArgVec[anArgIter];
411       DDocStd::GetDocument (aNameVar, aDoc, false);
412       if (aDoc.IsNull())
413       {
414         TopoDS_Shape aShape = DBRep::Get (aNameVar);
415         if (aShape.IsNull())
416         {
417           Message::SendFail() << "Syntax error: '" << aNameVar << "' is not a shape nor document";
418           return 1;
419         }
420
421         anApp->NewDocument (TCollection_ExtendedString ("BinXCAF"), aDoc);
422         Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (aDoc->Main());
423         aShapeTool->AddShape (aShape);
424       }
425     }
426     else if (aGltfFilePath.IsEmpty())
427     {
428       aGltfFilePath = theArgVec[anArgIter];
429     }
430     else if (anArgCase == "-texturesSeparate")
431     {
432       toEmbedTexturesInGlb = false;
433     }
434     else
435     {
436       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
437       return 1;
438     }
439   }
440   if (aGltfFilePath.IsEmpty())
441   {
442     Message::SendFail() << "Syntax error: wrong number of arguments";
443     return 1;
444   }
445
446   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
447
448   TCollection_AsciiString anExt = aGltfFilePath;
449   anExt.LowerCase();
450
451   const Standard_Real aSystemUnitFactor = UnitsMethods::GetCasCadeLengthUnit() * 0.001;
452
453   RWGltf_CafWriter aWriter (aGltfFilePath, anExt.EndsWith (".glb"));
454   aWriter.SetTransformationFormat (aTrsfFormat);
455   aWriter.SetNodeNameFormat (aNodeNameFormat);
456   aWriter.SetMeshNameFormat (aMeshNameFormat);
457   aWriter.SetForcedUVExport (toForceUVExport);
458   aWriter.SetToEmbedTexturesInGlb (toEmbedTexturesInGlb);
459   aWriter.ChangeCoordinateSystemConverter().SetInputLengthUnit (aSystemUnitFactor);
460   aWriter.ChangeCoordinateSystemConverter().SetInputCoordinateSystem (RWMesh_CoordinateSystem_Zup);
461   aWriter.Perform (aDoc, aFileInfo, aProgress->Start());
462   return 0;
463 }
464
465 static Standard_Integer writestl
466 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
467 {
468   if (argc < 3 || argc > 4) {
469     di << "Use: " << argv[0]
470     << " shape file [ascii/binary (0/1) : 1 by default]\n";
471   } else {
472     TopoDS_Shape aShape = DBRep::Get(argv[1]);
473     Standard_Boolean isASCIIMode = Standard_False;
474     if (argc == 4) {
475       isASCIIMode = (Draw::Atoi(argv[3]) == 0);
476     }
477     StlAPI_Writer aWriter;
478     aWriter.ASCIIMode() = isASCIIMode;
479     Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (di);
480     Standard_Boolean isOK = aWriter.Write (aShape, argv[2], aProgress->Start());
481     if (!isOK)
482        di << "** Error **: Mesh writing has been failed.\n";
483   }
484   return 0;
485 }
486
487 //=============================================================================
488 //function : readstl
489 //purpose  : Reads stl file
490 //=============================================================================
491 static Standard_Integer readstl(Draw_Interpretor& theDI,
492                                 Standard_Integer theArgc,
493                                 const char** theArgv)
494 {
495   TCollection_AsciiString aShapeName, aFilePath;
496   bool toCreateCompOfTris = false;
497   for (Standard_Integer anArgIter = 1; anArgIter < theArgc; ++anArgIter)
498   {
499     TCollection_AsciiString anArg (theArgv[anArgIter]);
500     anArg.LowerCase();
501     if (aShapeName.IsEmpty())
502     {
503       aShapeName = theArgv[anArgIter];
504     }
505     else if (aFilePath.IsEmpty())
506     {
507       aFilePath = theArgv[anArgIter];
508     }
509     else if (anArg == "-brep")
510     {
511       toCreateCompOfTris = true;
512       if (anArgIter + 1 < theArgc
513        && Draw::ParseOnOff (theArgv[anArgIter + 1], toCreateCompOfTris))
514       {
515         ++anArgIter;
516       }
517     }
518     else
519     {
520       Message::SendFail() << "Syntax error: unknown argument '" << theArgv[anArgIter] << "'";
521       return 1;
522     }
523   }
524   if (aFilePath.IsEmpty())
525   {
526     Message::SendFail() << "Syntax error: not enough arguments";
527     return 1;
528   }
529
530   TopoDS_Shape aShape;
531   if (!toCreateCompOfTris)
532   {
533     // Read STL file to the triangulation.
534     Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
535     Handle(Poly_Triangulation) aTriangulation = RWStl::ReadFile (aFilePath.ToCString(), aProgress->Start());
536
537     TopoDS_Face aFace;
538     BRep_Builder aB;
539     aB.MakeFace (aFace);
540     aB.UpdateFace (aFace, aTriangulation);
541     aShape = aFace;
542   }
543   else
544   {
545     Standard_DISABLE_DEPRECATION_WARNINGS
546     StlAPI::Read(aShape, aFilePath.ToCString());
547     Standard_ENABLE_DEPRECATION_WARNINGS
548   }
549   DBRep::Set (aShapeName.ToCString(), aShape);
550   return 0;
551 }
552
553 //! Parse RWMesh_CoordinateSystem enumeration.
554 static Standard_Boolean parseCoordinateSystem (const char* theArg,
555                                                RWMesh_CoordinateSystem& theSystem)
556 {
557   TCollection_AsciiString aCSStr (theArg);
558   aCSStr.LowerCase();
559   if (aCSStr == "zup")
560   {
561     theSystem = RWMesh_CoordinateSystem_Zup;
562   }
563   else if (aCSStr == "yup")
564   {
565     theSystem = RWMesh_CoordinateSystem_Yup;
566   }
567   else
568   {
569     return Standard_False;
570   }
571   return Standard_True;
572 }
573
574 //=============================================================================
575 //function : ReadObj
576 //purpose  : Reads OBJ file
577 //=============================================================================
578 static Standard_Integer ReadObj (Draw_Interpretor& theDI,
579                                  Standard_Integer theNbArgs,
580                                  const char** theArgVec)
581 {
582   TCollection_AsciiString aDestName, aFilePath;
583   Standard_Boolean toUseExistingDoc = Standard_False;
584   Standard_Real aFileUnitFactor = -1.0;
585   RWMesh_CoordinateSystem aResultCoordSys = RWMesh_CoordinateSystem_Zup, aFileCoordSys = RWMesh_CoordinateSystem_Yup;
586   Standard_Boolean toListExternalFiles = Standard_False, isSingleFace = Standard_False, isSinglePrecision = Standard_False;
587   Standard_Boolean isNoDoc = (TCollection_AsciiString(theArgVec[0]) == "readobj");
588   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
589   {
590     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
591     anArgCase.LowerCase();
592     if (anArgIter + 1 < theNbArgs
593      && (anArgCase == "-unit"
594       || anArgCase == "-units"
595       || anArgCase == "-fileunit"
596       || anArgCase == "-fileunits"))
597     {
598       const TCollection_AsciiString aUnitStr (theArgVec[++anArgIter]);
599       aFileUnitFactor = UnitsAPI::AnyToSI (1.0, aUnitStr.ToCString());
600       if (aFileUnitFactor <= 0.0)
601       {
602         Message::SendFail() << "Syntax error: wrong length unit '" << aUnitStr << "'";
603         return 1;
604       }
605     }
606     else if (anArgIter + 1 < theNbArgs
607           && (anArgCase == "-filecoordinatesystem"
608            || anArgCase == "-filecoordsystem"
609            || anArgCase == "-filecoordsys"))
610     {
611       if (!parseCoordinateSystem (theArgVec[++anArgIter], aFileCoordSys))
612       {
613         Message::SendFail() << "Syntax error: unknown coordinate system '" << theArgVec[anArgIter] << "'";
614         return 1;
615       }
616     }
617     else if (anArgIter + 1 < theNbArgs
618           && (anArgCase == "-resultcoordinatesystem"
619            || anArgCase == "-resultcoordsystem"
620            || anArgCase == "-resultcoordsys"
621            || anArgCase == "-rescoordsys"))
622     {
623       if (!parseCoordinateSystem (theArgVec[++anArgIter], aResultCoordSys))
624       {
625         Message::SendFail() << "Syntax error: unknown coordinate system '" << theArgVec[anArgIter] << "'";
626         return 1;
627       }
628     }
629     else if (anArgCase == "-singleprecision"
630           || anArgCase == "-singleprec")
631     {
632       isSinglePrecision = Standard_True;
633       if (anArgIter + 1 < theNbArgs
634        && Draw::ParseOnOff (theArgVec[anArgIter + 1], isSinglePrecision))
635       {
636         ++anArgIter;
637       }
638     }
639     else if (isNoDoc
640           && (anArgCase == "-singleface"
641            || anArgCase == "-singletriangulation"))
642     {
643       isSingleFace = Standard_True;
644     }
645     else if (!isNoDoc
646           && (anArgCase == "-nocreate"
647            || anArgCase == "-nocreatedoc"))
648     {
649       toUseExistingDoc = Standard_True;
650       if (anArgIter + 1 < theNbArgs
651        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toUseExistingDoc))
652       {
653         ++anArgIter;
654       }
655     }
656     else if (anArgCase == "-listexternalfiles"
657           || anArgCase == "-listexternals"
658           || anArgCase == "-listexternal"
659           || anArgCase == "-external"
660           || anArgCase == "-externalfiles")
661     {
662       toListExternalFiles = Standard_True;
663     }
664     else if (aDestName.IsEmpty())
665     {
666       aDestName = theArgVec[anArgIter];
667     }
668     else if (aFilePath.IsEmpty())
669     {
670       aFilePath = theArgVec[anArgIter];
671     }
672     else
673     {
674       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
675       return 1;
676     }
677   }
678   if (aFilePath.IsEmpty())
679   {
680     Message::SendFail() << "Syntax error: wrong number of arguments";
681     return 1;
682   }
683
684   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
685   Handle(TDocStd_Document) aDoc;
686   if (!isNoDoc
687    && !toListExternalFiles)
688   {
689     Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
690     Standard_CString aNameVar = aDestName.ToCString();
691     DDocStd::GetDocument (aNameVar, aDoc, Standard_False);
692     if (aDoc.IsNull())
693     {
694       if (toUseExistingDoc)
695       {
696         Message::SendFail() << "Error: document with name " << aDestName << " does not exist";
697         return 1;
698       }
699       anApp->NewDocument (TCollection_ExtendedString ("BinXCAF"), aDoc);
700     }
701     else if (!toUseExistingDoc)
702     {
703       Message::SendFail() << "Error: document with name " << aDestName << " already exists";
704       return 1;
705     }
706   }
707
708   RWObj_CafReader aReader;
709   aReader.SetSinglePrecision (isSinglePrecision);
710   aReader.SetSystemLengthUnit (UnitsMethods::GetCasCadeLengthUnit() * 0.001);
711   aReader.SetSystemCoordinateSystem (aResultCoordSys);
712   aReader.SetFileLengthUnit (aFileUnitFactor);
713   aReader.SetFileCoordinateSystem (aFileCoordSys);
714   aReader.SetDocument (aDoc);
715   if (isSingleFace)
716   {
717     RWObj_TriangulationReader aSimpleReader;
718     aSimpleReader.SetSinglePrecision (isSinglePrecision);
719     aSimpleReader.SetCreateShapes (Standard_False);
720     aSimpleReader.SetTransformation (aReader.CoordinateSystemConverter());
721     aSimpleReader.Read (aFilePath.ToCString(), aProgress->Start());
722
723     Handle(Poly_Triangulation) aTriangulation = aSimpleReader.GetTriangulation();
724     TopoDS_Face aFace;
725     BRep_Builder aBuiler;
726     aBuiler.MakeFace (aFace);
727     aBuiler.UpdateFace (aFace, aTriangulation);
728     DBRep::Set (aDestName.ToCString(), aFace);
729     return 0;
730   }
731
732   if (toListExternalFiles)
733   {
734     aReader.ProbeHeader (aFilePath);
735     for (NCollection_IndexedMap<TCollection_AsciiString>::Iterator aFileIter (aReader.ExternalFiles()); aFileIter.More(); aFileIter.Next())
736     {
737       theDI << "\"" << aFileIter.Value() << "\" ";
738     }
739   }
740   else
741   {
742     aReader.Perform (aFilePath, aProgress->Start());
743     if (isNoDoc)
744     {
745       DBRep::Set (aDestName.ToCString(), aReader.SingleShape());
746     }
747     else
748     {
749       Handle(DDocStd_DrawDocument) aDrawDoc = new DDocStd_DrawDocument (aDoc);
750       TDataStd_Name::Set (aDoc->GetData()->Root(), aDestName);
751       Draw::Set (aDestName.ToCString(), aDrawDoc);
752     }
753   }
754   return 0;
755 }
756
757 //=============================================================================
758 //function : WriteObj
759 //purpose  : Writes OBJ file
760 //=============================================================================
761 static Standard_Integer WriteObj (Draw_Interpretor& theDI,
762                                   Standard_Integer theNbArgs,
763                                   const char** theArgVec)
764 {
765   TCollection_AsciiString anObjFilePath;
766   Handle(TDocStd_Document) aDoc;
767   Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
768   TColStd_IndexedDataMapOfStringString aFileInfo;
769   Standard_Real aFileUnitFactor = -1.0;
770   RWMesh_CoordinateSystem aSystemCoordSys = RWMesh_CoordinateSystem_Zup, aFileCoordSys = RWMesh_CoordinateSystem_Yup;
771   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
772   {
773     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
774     anArgCase.LowerCase();
775         if (anArgIter + 1 < theNbArgs
776      && (anArgCase == "-unit"
777       || anArgCase == "-units"
778       || anArgCase == "-fileunit"
779       || anArgCase == "-fileunits"))
780     {
781       const TCollection_AsciiString aUnitStr (theArgVec[++anArgIter]);
782       aFileUnitFactor = UnitsAPI::AnyToSI (1.0, aUnitStr.ToCString());
783       if (aFileUnitFactor <= 0.0)
784       {
785         Message::SendFail() << "Syntax error: wrong length unit '" << aUnitStr << "'";
786         return 1;
787       }
788     }
789     else if (anArgIter + 1 < theNbArgs
790           && (anArgCase == "-filecoordinatesystem"
791            || anArgCase == "-filecoordsystem"
792            || anArgCase == "-filecoordsys"))
793     {
794       if (!parseCoordinateSystem (theArgVec[++anArgIter], aFileCoordSys))
795       {
796         Message::SendFail() << "Syntax error: unknown coordinate system '" << theArgVec[anArgIter] << "'";
797         return 1;
798       }
799     }
800     else if (anArgIter + 1 < theNbArgs
801           && (anArgCase == "-systemcoordinatesystem"
802            || anArgCase == "-systemcoordsystem"
803            || anArgCase == "-systemcoordsys"
804            || anArgCase == "-syscoordsys"))
805     {
806       if (!parseCoordinateSystem (theArgVec[++anArgIter], aSystemCoordSys))
807       {
808         Message::SendFail() << "Syntax error: unknown coordinate system '" << theArgVec[anArgIter] << "'";
809         return 1;
810       }
811     }
812     else if (anArgCase == "-comments"
813           && anArgIter + 1 < theNbArgs)
814     {
815       aFileInfo.Add ("Comments", theArgVec[++anArgIter]);
816     }
817     else if (anArgCase == "-author"
818           && anArgIter + 1 < theNbArgs)
819     {
820       aFileInfo.Add ("Author", theArgVec[++anArgIter]);
821     }
822     else if (aDoc.IsNull())
823     {
824       Standard_CString aNameVar = theArgVec[anArgIter];
825       DDocStd::GetDocument (aNameVar, aDoc, false);
826       if (aDoc.IsNull())
827       {
828         TopoDS_Shape aShape = DBRep::Get (aNameVar);
829         if (aShape.IsNull())
830         {
831           Message::SendFail() << "Syntax error: '" << aNameVar << "' is not a shape nor document";
832           return 1;
833         }
834
835         anApp->NewDocument (TCollection_ExtendedString ("BinXCAF"), aDoc);
836         Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (aDoc->Main());
837         aShapeTool->AddShape (aShape);
838       }
839     }
840     else if (anObjFilePath.IsEmpty())
841     {
842       anObjFilePath = theArgVec[anArgIter];
843     }
844     else
845     {
846       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
847       return 1;
848     }
849   }
850   if (anObjFilePath.IsEmpty())
851   {
852     Message::SendFail() << "Syntax error: wrong number of arguments";
853     return 1;
854   }
855
856   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
857
858   const Standard_Real aSystemUnitFactor = UnitsMethods::GetCasCadeLengthUnit() * 0.001;
859   RWObj_CafWriter aWriter (anObjFilePath);
860   aWriter.ChangeCoordinateSystemConverter().SetInputLengthUnit (aSystemUnitFactor);
861   aWriter.ChangeCoordinateSystemConverter().SetInputCoordinateSystem (aSystemCoordSys);
862   aWriter.ChangeCoordinateSystemConverter().SetOutputLengthUnit (aFileUnitFactor);
863   aWriter.ChangeCoordinateSystemConverter().SetOutputCoordinateSystem (aFileCoordSys);
864   aWriter.Perform (aDoc, aFileInfo, aProgress->Start());
865   return 0;
866 }
867
868 static Standard_Integer writevrml
869 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
870 {
871   if (argc < 3 || argc > 5) 
872   {
873     di << "wrong number of parameters\n";
874     return 0;
875   }
876
877   TopoDS_Shape aShape = DBRep::Get(argv[1]);
878
879   // Get the optional parameters
880   Standard_Integer aVersion = 2;
881   Standard_Integer aType = 1;
882   if (argc >= 4)
883   {
884     aVersion = Draw::Atoi(argv[3]);
885     if (argc == 5)
886       aType = Draw::Atoi(argv[4]);
887   }
888
889   // Bound parameters
890   aVersion = Max(1, aVersion);
891   aVersion = Min(2, aVersion);
892   aType = Max(0, aType);
893   aType = Min(2, aType);
894
895   VrmlAPI_Writer writer;
896
897   switch (aType)
898   {
899   case 0: writer.SetRepresentation(VrmlAPI_ShadedRepresentation); break;
900   case 1: writer.SetRepresentation(VrmlAPI_WireFrameRepresentation); break;
901   case 2: writer.SetRepresentation(VrmlAPI_BothRepresentation); break;
902   }
903
904   if (!writer.Write(aShape, argv[2], aVersion))
905   {
906     di << "Error: File " << argv[2] << " was not written\n";
907   }
908
909   return 0;
910 }
911
912 //=======================================================================
913 //function : loadvrml
914 //purpose  :
915 //=======================================================================
916
917 static Standard_Integer loadvrml
918 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
919 {
920   if (argc<3) di << "wrong number of parameters"    << "\n";
921   else {
922     TopoDS_Shape aShape ;
923     VrmlData_DataMapOfShapeAppearance aShapeAppMap;
924
925     //-----------------------------------------------------------
926     std::filebuf aFic;
927     std::istream aStream (&aFic);
928
929     if (aFic.open(argv[2], std::ios::in)) {
930
931       // Get path of the VRML file.
932       OSD_Path aPath(argv[2]);
933       TCollection_AsciiString aVrmlDir(".");
934       TCollection_AsciiString aDisk = aPath.Disk();
935       TCollection_AsciiString aTrek = aPath.Trek();
936       if (!aTrek.IsEmpty())
937       {
938         if (!aDisk.IsEmpty())
939           aVrmlDir = aDisk;
940         else
941           aVrmlDir.Clear();
942         aTrek.ChangeAll('|', '/');
943         aVrmlDir += aTrek;
944       }
945
946       VrmlData_Scene aScene;
947       Standard_Real anOCCUnit = UnitsMethods::GetCasCadeLengthUnit();
948       aScene.SetLinearScale(1000. / anOCCUnit);
949
950       aScene.SetVrmlDir (aVrmlDir);
951       aScene << aStream;
952       const char * aStr = 0L;
953       switch (aScene.Status()) {
954
955       case VrmlData_StatusOK:
956         {
957           aShape = aScene.GetShape(aShapeAppMap);
958           break;
959         }
960       case VrmlData_EmptyData:            aStr = "EmptyData"; break;
961       case VrmlData_UnrecoverableError:   aStr = "UnrecoverableError"; break;
962       case VrmlData_GeneralError:         aStr = "GeneralError"; break;
963       case VrmlData_EndOfFile:            aStr = "EndOfFile"; break;
964       case VrmlData_NotVrmlFile:          aStr = "NotVrmlFile"; break;
965       case VrmlData_CannotOpenFile:       aStr = "CannotOpenFile"; break;
966       case VrmlData_VrmlFormatError:      aStr = "VrmlFormatError"; break;
967       case VrmlData_NumericInputError:    aStr = "NumericInputError"; break;
968       case VrmlData_IrrelevantNumber:     aStr = "IrrelevantNumber"; break;
969       case VrmlData_BooleanInputError:    aStr = "BooleanInputError"; break;
970       case VrmlData_StringInputError:     aStr = "StringInputError"; break;
971       case VrmlData_NodeNameUnknown:      aStr = "NodeNameUnknown"; break;
972       case VrmlData_NonPositiveSize:      aStr = "NonPositiveSize"; break;
973       case VrmlData_ReadUnknownNode:      aStr = "ReadUnknownNode"; break;
974       case VrmlData_NonSupportedFeature:  aStr = "NonSupportedFeature"; break;
975       case VrmlData_OutputStreamUndefined:aStr = "OutputStreamUndefined"; break;
976       case VrmlData_NotImplemented:       aStr = "NotImplemented"; break;
977       default:
978         break;
979       }
980       if (aStr) {
981         di << " ++ VRML Error: " << aStr << " in line "
982           << aScene.GetLineError() << "\n";
983       }
984       else {
985         DBRep::Set(argv[1],aShape);
986       }
987     }
988     else {
989       di << "cannot open file\n";
990     }
991
992
993     //-----------------------------------------------------------
994   }
995   return 0;
996 }
997
998 //-----------------------------------------------------------------------------
999 static Standard_Integer createmesh
1000 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1001 {
1002   if (argc<3)
1003   {
1004     di << "Wrong number of parameters\n";
1005     di << "Use: " << argv[0] << " <mesh name> <stl file>\n";
1006     return 0;
1007   }
1008
1009   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1010   if (aContext.IsNull())
1011   {
1012     di << "No active view. Please call 'vinit' first\n";
1013     return 0;
1014   }
1015
1016   // Progress indicator
1017   OSD_Path aFile( argv[2] );
1018   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (di, 1);
1019   Handle(Poly_Triangulation) aSTLMesh = RWStl::ReadFile (aFile, aProgress->Start());
1020
1021   di << "Reading OK...\n";
1022   Handle( XSDRAWSTLVRML_DataSource ) aDS = new XSDRAWSTLVRML_DataSource( aSTLMesh );
1023   di << "Data source is created successful\n";
1024   Handle( MeshVS_Mesh ) aMesh = new MeshVS_Mesh();
1025   di << "MeshVS_Mesh is created successful\n";
1026
1027   aMesh->SetDataSource( aDS );
1028   aMesh->AddBuilder( new MeshVS_MeshPrsBuilder( aMesh.operator->() ), Standard_True );
1029
1030   aMesh->GetDrawer()->SetColor( MeshVS_DA_EdgeColor, Quantity_NOC_YELLOW );
1031
1032   // Hide all nodes by default
1033   Handle(TColStd_HPackedMapOfInteger) aNodes = new TColStd_HPackedMapOfInteger();
1034   const Standard_Integer aLen = aSTLMesh->NbNodes();
1035   for ( Standard_Integer anIndex = 1; anIndex <= aLen; anIndex++ )
1036     aNodes->ChangeMap().Add( anIndex );
1037   aMesh->SetHiddenNodes( aNodes );
1038   aMesh->SetSelectableNodes ( aNodes );
1039
1040   VDisplayAISObject(argv[1], aMesh);
1041   aContext->Deactivate( aMesh );
1042
1043   Draw::Set( argv[1], new XSDRAWSTLVRML_DrawableMesh( aMesh ) );
1044   Handle( V3d_View ) aView = ViewerTest::CurrentView();
1045   if ( !aView.IsNull() )
1046     aView->FitAll();
1047
1048   return 0;
1049 }
1050 //-----------------------------------------------------------------------------
1051
1052 static Standard_Integer create3d
1053 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1054 {
1055   if (argc<2)
1056   {
1057     di << "Wrong number of parameters\n";
1058     di << "Use: " << argv[0] << " <mesh name>\n";
1059     return 0;
1060   }
1061
1062   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1063   if (aContext.IsNull())
1064   {
1065     di << "No active view. Please call 'vinit' first\n";
1066     return 0;
1067   }
1068
1069   Handle( XSDRAWSTLVRML_DataSource3D ) aDS = new XSDRAWSTLVRML_DataSource3D();
1070   di << "Data source is created successful\n";
1071   Handle( MeshVS_Mesh ) aMesh = new MeshVS_Mesh();
1072   di << "MeshVS_Mesh is created successful\n";
1073
1074   aMesh->SetDataSource( aDS );
1075   aMesh->AddBuilder( new MeshVS_MeshPrsBuilder( aMesh.operator->() ), Standard_True );
1076
1077   aMesh->GetDrawer()->SetColor( MeshVS_DA_EdgeColor, Quantity_NOC_YELLOW );
1078
1079   // Hide all nodes by default
1080   Handle(TColStd_HPackedMapOfInteger) aNodes = new TColStd_HPackedMapOfInteger();
1081   Standard_Integer aLen = aDS->GetAllNodes().Extent();
1082   for ( Standard_Integer anIndex = 1; anIndex <= aLen; anIndex++ )
1083     aNodes->ChangeMap().Add( anIndex );
1084   aMesh->SetHiddenNodes( aNodes );
1085   aMesh->SetSelectableNodes ( aNodes );
1086
1087   VDisplayAISObject(argv[1], aMesh);
1088   aContext->Deactivate( aMesh );
1089
1090   Draw::Set( argv[1], new XSDRAWSTLVRML_DrawableMesh( aMesh ) );
1091   Handle( V3d_View ) aView = ViewerTest::CurrentView();
1092   if ( !aView.IsNull() )
1093     aView->FitAll();
1094
1095   return 0;
1096 }
1097
1098 Handle( MeshVS_Mesh ) getMesh( const char* theName, Draw_Interpretor& di)
1099 {
1100   Handle( XSDRAWSTLVRML_DrawableMesh ) aDrawMesh =
1101     Handle( XSDRAWSTLVRML_DrawableMesh )::DownCast( Draw::Get( theName ) );
1102
1103   if( aDrawMesh.IsNull() )
1104   {
1105     di << "There is no such object\n";
1106     return NULL;
1107   }
1108   else
1109   {
1110     Handle( MeshVS_Mesh ) aMesh = aDrawMesh->GetMesh();
1111     if( aMesh.IsNull() )
1112     {
1113       di << "There is invalid mesh\n";
1114       return NULL;
1115     }
1116     else
1117       return aMesh;
1118   }
1119 }
1120
1121 //-----------------------------------------------------------------------------
1122 static Standard_Integer setcolor
1123 (Draw_Interpretor& di, Standard_Integer argc, const char** argv, Standard_Integer theParam )
1124 {
1125   if (argc<5)
1126     di << "Wrong number of parameters\n";
1127   else
1128   {
1129     Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1130     if( !aMesh.IsNull() )
1131     {
1132       Standard_Real aRed = Draw::Atof (argv[2]);
1133       Standard_Real aGreen = Draw::Atof (argv[3]);
1134       Standard_Real aBlue = Draw::Atof (argv[4]);
1135       aMesh->GetDrawer()->SetColor( (MeshVS_DrawerAttribute)theParam,
1136                                     Quantity_Color( aRed, aGreen, aBlue, Quantity_TOC_RGB ) );
1137
1138       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1139
1140       if( aContext.IsNull() )
1141         di << "The context is null\n";
1142       else
1143         aContext->Redisplay (aMesh, Standard_True);
1144     }
1145   }
1146   return 0;
1147 }
1148 //-----------------------------------------------------------------------------
1149 static Standard_Integer meshcolor
1150 (Draw_Interpretor& theInterp, Standard_Integer argc, const char** argv )
1151 {
1152   return setcolor( theInterp, argc, argv, MeshVS_DA_InteriorColor );
1153 }
1154 //-----------------------------------------------------------------------------
1155 static Standard_Integer linecolor
1156 (Draw_Interpretor& theInterp, Standard_Integer argc, const char** argv )
1157 {
1158   return setcolor( theInterp, argc, argv, MeshVS_DA_EdgeColor );
1159 }
1160 //-----------------------------------------------------------------------------
1161 static Standard_Integer meshmat
1162 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1163 {
1164   if (argc<3)
1165     di << "Wrong number of parameters\n";
1166   else
1167   {
1168     Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1169     if( !aMesh.IsNull() )
1170     {
1171       Standard_Integer aMaterial = Draw::Atoi (argv[2]);
1172
1173       Graphic3d_MaterialAspect aMatAsp =
1174         (Graphic3d_MaterialAspect)(Graphic3d_NameOfMaterial)aMaterial;
1175
1176       if (argc == 4)
1177       {
1178         Standard_Real aTransparency = Draw::Atof(argv[3]);
1179         aMatAsp.SetTransparency (Standard_ShortReal (aTransparency));
1180       }
1181       aMesh->GetDrawer()->SetMaterial( MeshVS_DA_FrontMaterial, aMatAsp );
1182       aMesh->GetDrawer()->SetMaterial( MeshVS_DA_BackMaterial, aMatAsp );
1183
1184       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1185
1186       if( aContext.IsNull() )
1187         di << "The context is null\n";
1188       else
1189         aContext->Redisplay (aMesh, Standard_True);
1190     }
1191   }
1192   return 0;
1193 }
1194 //-----------------------------------------------------------------------------
1195 static Standard_Integer shrink
1196 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1197 {
1198   if (argc<3)
1199     di << "Wrong number of parameters\n";
1200   else
1201   {
1202     Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1203     if( !aMesh.IsNull() )
1204     {
1205       Standard_Real aShrinkCoeff = Draw::Atof (argv[2]);
1206       aMesh->GetDrawer()->SetDouble( MeshVS_DA_ShrinkCoeff, aShrinkCoeff );
1207
1208       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1209
1210       if( aContext.IsNull() )
1211         di << "The context is null\n";
1212       else
1213         aContext->Redisplay (aMesh, Standard_True);
1214     }
1215   }
1216   return 0;
1217 }
1218
1219 //-----------------------------------------------------------------------------
1220 static Standard_Integer closed (Draw_Interpretor& theDI, Standard_Integer theArgc, const char** theArgv)
1221 {
1222   if (theArgc < 3)
1223   {
1224     theDI << "Wrong number of parameters.\n";
1225   }
1226   else
1227   {
1228     Handle(MeshVS_Mesh) aMesh = getMesh (theArgv[1], theDI);
1229     if (!aMesh.IsNull())
1230     {
1231       Standard_Boolean aFlag = Draw::Atoi (theArgv[2]) != 0;
1232       aMesh->GetDrawer()->SetBoolean (MeshVS_DA_SupressBackFaces, aFlag);
1233
1234       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1235       if (aContext.IsNull())
1236       {
1237         theDI << "The context is null\n";
1238       }
1239       else
1240       {
1241         aContext->Redisplay (aMesh, Standard_True);
1242       }
1243     }
1244   }
1245   return 0;
1246 }
1247
1248 //-----------------------------------------------------------------------------
1249
1250 static Standard_Integer mdisplay
1251 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1252 {
1253   if (argc<2)
1254     di << "Wrong number of parameters\n";
1255   else
1256   {
1257     Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1258     if( !aMesh.IsNull() )
1259     {
1260       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1261
1262       if( aContext.IsNull() )
1263         di << "The context is null\n";
1264       else
1265       {
1266         aContext->Display (aMesh, Standard_True);
1267       }
1268     }
1269   }
1270   return 0;
1271 }
1272 //-----------------------------------------------------------------------------
1273 static Standard_Integer merase
1274 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1275 {
1276   if (argc<2)
1277     di << "Wrong number of parameters\n";
1278   else
1279   {
1280     Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1281     if( !aMesh.IsNull() )
1282     {
1283       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1284
1285       if( aContext.IsNull() )
1286         di << "The context is null\n";
1287       else
1288       {
1289         aContext->Erase (aMesh, Standard_True);
1290       }
1291     }
1292     else
1293       di << "Mesh is null\n";
1294   }
1295   return 0;
1296 }
1297 //-----------------------------------------------------------------------------
1298 static Standard_Integer hidesel
1299 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1300 {
1301   if (argc<2)
1302   {
1303     di << "Wrong number of parameters\n";
1304     di << "Use: " << argv[0] << " <mesh name>\n";
1305     return 0;
1306   }
1307
1308   Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1309   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1310   if( aMesh.IsNull() )
1311   {
1312     di << "The mesh is invalid\n";
1313     return 0;
1314   }
1315
1316   if( aContext.IsNull() )
1317     di << "The context is null\n";
1318   else
1319   {
1320     Handle(TColStd_HPackedMapOfInteger) aHiddenNodes = aMesh->GetHiddenNodes();
1321     if (aHiddenNodes.IsNull())
1322     {
1323       aHiddenNodes = new TColStd_HPackedMapOfInteger();
1324     }
1325     Handle(TColStd_HPackedMapOfInteger) aHiddenElements = aMesh->GetHiddenElems();
1326     if (aHiddenElements.IsNull())
1327     {
1328       aHiddenElements = new TColStd_HPackedMapOfInteger();
1329     }
1330     for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
1331     {
1332       Handle( MeshVS_MeshEntityOwner ) anOwner =
1333         Handle( MeshVS_MeshEntityOwner )::DownCast( aContext->SelectedOwner() );
1334       if( !anOwner.IsNull() )
1335       {
1336         if( anOwner->Type()==MeshVS_ET_Node )
1337         {
1338           aHiddenNodes->ChangeMap().Add( anOwner->ID() );
1339         }
1340         else
1341         {
1342           aHiddenElements->ChangeMap().Add( anOwner->ID() );
1343         }
1344       }
1345     }
1346     aContext->ClearSelected (Standard_False);
1347     aMesh->SetHiddenNodes( aHiddenNodes );
1348     aMesh->SetHiddenElems( aHiddenElements );
1349     aContext->Redisplay (aMesh, Standard_True);
1350   }
1351
1352   return 0;
1353 }
1354 //-----------------------------------------------------------------------------
1355 static Standard_Integer showonly
1356 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1357 {
1358   if (argc<2)
1359   {
1360     di << "Wrong number of parameters\n";
1361     di << "Use: " << argv[0] << " <mesh name>\n";
1362     return 0;
1363   }
1364
1365
1366   Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1367   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1368   if( aMesh.IsNull() )
1369   {
1370     di << "The mesh is invalid\n";
1371     return 0;
1372   }
1373
1374   if( aContext.IsNull() )
1375     di << "The context is null\n";
1376   else
1377   {
1378     Handle(TColStd_HPackedMapOfInteger) aHiddenNodes =
1379       new TColStd_HPackedMapOfInteger(aMesh->GetDataSource()->GetAllNodes());
1380     Handle(TColStd_HPackedMapOfInteger) aHiddenElements =
1381       new TColStd_HPackedMapOfInteger(aMesh->GetDataSource()->GetAllElements());
1382     for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
1383     {
1384       Handle( MeshVS_MeshEntityOwner ) anOwner =
1385         Handle( MeshVS_MeshEntityOwner )::DownCast( aContext->SelectedOwner() );
1386       if( !anOwner.IsNull() )
1387       {
1388         if( anOwner->Type() == MeshVS_ET_Node )
1389         {
1390           aHiddenNodes->ChangeMap().Remove( anOwner->ID() );
1391         }
1392         else
1393         {
1394           aHiddenElements->ChangeMap().Remove( anOwner->ID() );
1395         }
1396       }
1397     }
1398     aMesh->SetHiddenNodes( aHiddenNodes );
1399     aMesh->SetHiddenElems( aHiddenElements );
1400     aContext->Redisplay (aMesh, Standard_True);
1401   }
1402
1403   return 0;
1404 }
1405 //-----------------------------------------------------------------------------
1406 static Standard_Integer showall
1407 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1408 {
1409   if (argc<2)
1410   {
1411     di << "Wrong number of parameters\n";
1412     di << "Use: " << argv[0] << " <mesh name>\n";
1413     return 0;
1414   }
1415
1416   Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1417   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1418   if( aMesh.IsNull() )
1419   {
1420     di << "The mesh is invalid\n";
1421     return 0;
1422   }
1423
1424   if( aContext.IsNull() )
1425     di << "The context is null\n";
1426   else
1427   {
1428     aMesh->SetHiddenNodes( new TColStd_HPackedMapOfInteger() );
1429     aMesh->SetHiddenElems( new TColStd_HPackedMapOfInteger() );
1430     aContext->Redisplay (aMesh, Standard_True);
1431   }
1432
1433   return 0;
1434 }
1435
1436 //-----------------------------------------------------------------------------
1437 static Standard_Integer meshcolors( Draw_Interpretor& di,
1438                                     Standard_Integer argc,
1439                                     const char** argv )
1440 {
1441   try
1442   {
1443     OCC_CATCH_SIGNALS
1444       if ( argc < 4 )
1445       {
1446         di << "Wrong number of parameters\n";
1447         di << "Use : meshcolors <mesh name> <mode> <isreflect>\n";
1448         di << "mode : {elem1|elem2|nodal|nodaltex|none}\n";
1449         di << "       elem1 - different color for each element\n";
1450         di << "       elem2 - one color for one side\n";
1451         di << "       nodal - different color for each node\n";
1452         di << "       nodaltex - different color for each node with texture interpolation\n";
1453         di << "       none  - clear\n";
1454         di << "isreflect : {0|1} \n";
1455
1456         return 0;
1457       }
1458
1459       Handle( MeshVS_Mesh ) aMesh = getMesh( argv[ 1 ], di );
1460
1461       if ( aMesh.IsNull() )
1462       {
1463         di << "Mesh not found\n";
1464         return 0;
1465       }
1466       Handle(AIS_InteractiveContext) anIC = ViewerTest::GetAISContext();
1467       if ( anIC.IsNull() )
1468       {
1469         di << "The context is null\n";
1470         return 0;
1471       }
1472       if( !aMesh.IsNull() )
1473       {
1474         TCollection_AsciiString aMode = TCollection_AsciiString (argv[2]);
1475         Quantity_Color aColor1(Quantity_NOC_BLUE1);
1476         Quantity_Color aColor2(Quantity_NOC_RED1);
1477         if( aMode.IsEqual("elem1") || aMode.IsEqual("elem2") || aMode.IsEqual("nodal") || aMode.IsEqual("nodaltex") || aMode.IsEqual("none") )
1478         {
1479           Handle(MeshVS_PrsBuilder) aTempBuilder;
1480           Standard_Integer aReflection = Draw::Atoi(argv[3]);
1481
1482           for (Standard_Integer aCount = 0 ; aCount < aMesh->GetBuildersCount(); aCount++ ){
1483             aTempBuilder = aMesh->FindBuilder("MeshVS_ElementalColorPrsBuilder");
1484             if( !aTempBuilder.IsNull())
1485               aMesh->RemoveBuilderById(aTempBuilder->GetId());
1486
1487             aTempBuilder = aMesh->FindBuilder("MeshVS_NodalColorPrsBuilder");
1488             if( !aTempBuilder.IsNull())
1489               aMesh->RemoveBuilderById(aTempBuilder->GetId());
1490           }
1491
1492           if( aMode.IsEqual("elem1") || aMode.IsEqual("elem2") )
1493           {
1494             Handle(MeshVS_ElementalColorPrsBuilder) aBuilder = new MeshVS_ElementalColorPrsBuilder(
1495                 aMesh, MeshVS_DMF_ElementalColorDataPrs | MeshVS_DMF_OCCMask );
1496               // Color
1497             const TColStd_PackedMapOfInteger& anAllElements = aMesh->GetDataSource()->GetAllElements();
1498             TColStd_MapIteratorOfPackedMapOfInteger anIter( anAllElements );
1499
1500             if( aMode.IsEqual("elem1") )
1501               for ( ; anIter.More(); anIter.Next() )
1502               {
1503                 Quantity_Color aColor( (Quantity_NameOfColor)( anIter.Key() % Quantity_NOC_WHITE ) );
1504                 aBuilder->SetColor1( anIter.Key(), aColor );
1505               }
1506             else
1507               for ( ; anIter.More(); anIter.Next() )
1508                 aBuilder->SetColor2( anIter.Key(), aColor1, aColor2 );
1509
1510             aMesh->AddBuilder( aBuilder, Standard_True );
1511           }
1512
1513
1514           if( aMode.IsEqual("nodal") )
1515           {
1516             Handle(MeshVS_NodalColorPrsBuilder) aBuilder = new MeshVS_NodalColorPrsBuilder(
1517                 aMesh, MeshVS_DMF_NodalColorDataPrs | MeshVS_DMF_OCCMask );
1518             aMesh->AddBuilder( aBuilder, Standard_True );
1519
1520             // Color
1521             const TColStd_PackedMapOfInteger& anAllNodes =
1522               aMesh->GetDataSource()->GetAllNodes();
1523             TColStd_MapIteratorOfPackedMapOfInteger anIter( anAllNodes );
1524             for ( ; anIter.More(); anIter.Next() )
1525             {
1526               Quantity_Color aColor( (Quantity_NameOfColor)(
1527                 anIter.Key() % Quantity_NOC_WHITE ) );
1528               aBuilder->SetColor( anIter.Key(), aColor );
1529             }
1530             aMesh->AddBuilder( aBuilder, Standard_True );
1531           }
1532
1533           if(aMode.IsEqual("nodaltex"))
1534           {
1535             // assign nodal builder to the mesh
1536             Handle(MeshVS_NodalColorPrsBuilder) aBuilder = new MeshVS_NodalColorPrsBuilder(
1537                    aMesh, MeshVS_DMF_NodalColorDataPrs | MeshVS_DMF_OCCMask);
1538             aMesh->AddBuilder(aBuilder, Standard_True);
1539             aBuilder->UseTexture(Standard_True);
1540
1541             // prepare color map for texture
1542             Aspect_SequenceOfColor aColorMap;
1543             aColorMap.Append((Quantity_NameOfColor) Quantity_NOC_RED);
1544             aColorMap.Append((Quantity_NameOfColor) Quantity_NOC_YELLOW);
1545             aColorMap.Append((Quantity_NameOfColor) Quantity_NOC_BLUE1);
1546
1547             // prepare scale map for mesh - it will be assigned to mesh as texture coordinates
1548             // make mesh color interpolated from minimum X coord to maximum X coord
1549             Handle(MeshVS_DataSource) aDataSource = aMesh->GetDataSource();
1550             Standard_Real aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ;
1551
1552             // get bounding box for calculations
1553             aDataSource->GetBoundingBox().Get(aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ);
1554             Standard_Real aDelta = aMaxX - aMinX;
1555
1556             // assign color scale map values (0..1) to nodes
1557             TColStd_DataMapOfIntegerReal aScaleMap;
1558             TColStd_Array1OfReal aCoords(1, 3);
1559             Standard_Integer     aNbNodes;
1560             MeshVS_EntityType    aType;
1561
1562             // iterate nodes
1563             const TColStd_PackedMapOfInteger& anAllNodes =
1564                   aMesh->GetDataSource()->GetAllNodes();
1565             TColStd_MapIteratorOfPackedMapOfInteger anIter(anAllNodes);
1566             for (; anIter.More(); anIter.Next())
1567             {
1568               //get node coordinates to aCoord variable
1569               aDataSource->GetGeom(anIter.Key(), Standard_False, aCoords, aNbNodes, aType);
1570
1571               Standard_Real aScaleValue;
1572               try {
1573                 OCC_CATCH_SIGNALS
1574                 aScaleValue = (aCoords.Value(1) - (Standard_Real) aMinX) / aDelta;
1575               } catch(Standard_Failure const&) {
1576                 aScaleValue = 0;
1577               }
1578
1579               aScaleMap.Bind(anIter.Key(), aScaleValue);
1580             }
1581
1582             //set color map for builder and a color for invalid scale value
1583             aBuilder->SetColorMap(aColorMap);
1584             aBuilder->SetInvalidColor(Quantity_NOC_BLACK);
1585             aBuilder->SetTextureCoords(aScaleMap);
1586             aMesh->AddBuilder(aBuilder, Standard_True);
1587           }
1588
1589           aMesh->GetDrawer()->SetBoolean (MeshVS_DA_ColorReflection, aReflection != 0);
1590
1591           anIC->Redisplay (aMesh, Standard_True);
1592         }
1593         else
1594         {
1595           di << "Wrong mode name\n";
1596           return 0;
1597         }
1598       }
1599   }
1600   catch ( Standard_Failure const& )
1601   {
1602     di << "Error\n";
1603   }
1604
1605   return 0;
1606 }
1607 //-----------------------------------------------------------------------------
1608 static Standard_Integer meshvectors( Draw_Interpretor& di,
1609                                      Standard_Integer argc,
1610                                      const char** argv )
1611 {
1612   if ( argc < 3 )
1613   {
1614     di << "Wrong number of parameters\n";
1615     di << "Use : meshvectors <mesh name> < -mode {elem|nodal|none} > [-maxlen len] [-color name] [-arrowpart ratio] [-issimple {1|0}]\n";
1616     di << "Supported mode values:\n";
1617     di << "       elem  - vector per element\n";
1618     di << "       nodal - vector per node\n";
1619     di << "       none  - clear\n";
1620
1621     return 0;
1622   }
1623
1624   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[ 1 ], di );
1625
1626   if ( aMesh.IsNull() )
1627   {
1628     di << "Mesh not found\n";
1629     return 0;
1630   }
1631   Handle(AIS_InteractiveContext) anIC = ViewerTest::GetAISContext();
1632   if ( anIC.IsNull() )
1633   {
1634     di << "The context is null\n";
1635     return 0;
1636   }
1637
1638   TCollection_AsciiString aParam;
1639   TCollection_AsciiString aMode("none");
1640   Standard_Real           aMaxlen(1.0);
1641   Quantity_Color          aColor(Quantity_NOC_ORANGE);
1642   Standard_Real           anArrowPart(0.1);
1643   Standard_Boolean        isSimplePrs(Standard_False);
1644
1645   for (Standard_Integer anIdx = 2; anIdx < argc; anIdx++)
1646   {
1647     if (!aParam.IsEmpty())
1648     {
1649       if (aParam == "-mode")
1650       {
1651         aMode       = argv[anIdx];
1652       }
1653       else if (aParam == "-maxlen")
1654       {
1655         aMaxlen     = Draw::Atof(argv[anIdx]);
1656       }
1657       else if (aParam == "-color")
1658       {
1659         if (!Quantity_Color::ColorFromName (argv[anIdx], aColor))
1660         {
1661           Message::SendFail() << "Syntax error at " << aParam;
1662           return 1;
1663         }
1664       }
1665       else if (aParam == "-arrowpart")
1666       {
1667         anArrowPart = Draw::Atof(argv[anIdx]);
1668       }
1669       else if (aParam == "-issimple")
1670       {
1671         isSimplePrs = Draw::Atoi(argv[anIdx]) != 0;
1672       }
1673       aParam.Clear();
1674     }
1675     else if (argv[anIdx][0] == '-')
1676     {
1677       aParam = argv[anIdx];
1678     }
1679   }
1680
1681   if( !aMode.IsEqual("elem") && !aMode.IsEqual("nodal") && !aMode.IsEqual("none") )
1682   {
1683     di << "Wrong mode name\n";
1684     return 0;
1685   }
1686
1687   Handle(MeshVS_PrsBuilder) aTempBuilder;
1688
1689   aTempBuilder = aMesh->FindBuilder("MeshVS_VectorPrsBuilder");
1690   if( !aTempBuilder.IsNull())
1691     aMesh->RemoveBuilderById(aTempBuilder->GetId());
1692
1693   if( !aMode.IsEqual("none") )
1694   {
1695     Handle(MeshVS_VectorPrsBuilder) aBuilder = new MeshVS_VectorPrsBuilder( aMesh.operator->(), 
1696                                                                             aMaxlen,
1697                                                                             aColor,
1698                                                                             MeshVS_DMF_VectorDataPrs,
1699                                                                             0,
1700                                                                             -1,
1701                                                                             MeshVS_BP_Vector,
1702                                                                             isSimplePrs);
1703
1704     Standard_Boolean anIsElement = aMode.IsEqual("elem");
1705     const TColStd_PackedMapOfInteger& anAllIDs = anIsElement ? aMesh->GetDataSource()->GetAllElements() :
1706                                                                aMesh->GetDataSource()->GetAllNodes();
1707
1708     Standard_Integer aNbNodes;
1709     MeshVS_EntityType aEntType;
1710
1711     TColStd_Array1OfReal aCoords(1, 3);
1712     aCoords.Init (0.);
1713     TColStd_MapIteratorOfPackedMapOfInteger anIter( anAllIDs );
1714     for ( ; anIter.More(); anIter.Next() )
1715     {
1716       Standard_Boolean IsValidData = Standard_False; 
1717       if (anIsElement) {
1718         aMesh->GetDataSource()->GetGeomType(anIter.Key(), anIsElement, aEntType);
1719         if (aEntType == MeshVS_ET_Face)
1720           IsValidData = aMesh->GetDataSource()->GetNormal(anIter.Key(), 3, aCoords.ChangeValue(1), aCoords.ChangeValue(2), aCoords.ChangeValue(3));
1721       } else
1722         IsValidData = aMesh->GetDataSource()->GetGeom(anIter.Key(), Standard_False, aCoords, aNbNodes, aEntType);
1723
1724       gp_Vec aNorm;
1725       if(IsValidData)
1726       { 
1727         aNorm = gp_Vec(aCoords.Value(1), aCoords.Value(2), aCoords.Value(3));
1728         if(aNorm.Magnitude() < gp::Resolution())
1729         {
1730           aNorm = gp_Vec(0,0,1); //method GetGeom(...) returns coordinates of nodes
1731         }
1732       }
1733       else
1734       {
1735         aNorm = gp_Vec(0,0,1);
1736       }
1737       aBuilder->SetVector(anIsElement, anIter.Key(), aNorm.Normalized());
1738     }
1739
1740     aMesh->AddBuilder( aBuilder, Standard_False );
1741     aMesh->GetDrawer()->SetDouble ( MeshVS_DA_VectorArrowPart, anArrowPart );
1742   }
1743
1744   anIC->Redisplay (aMesh, Standard_True);
1745
1746   return 0;
1747 }
1748 //-----------------------------------------------------------------------------
1749
1750 static Standard_Integer meshtext( Draw_Interpretor& di,
1751                                   Standard_Integer argc,
1752                                   const char** argv )
1753 {
1754   if ( argc < 2 )
1755   {
1756     di << "Wrong number of parameters\n";
1757     di << "Use : meshtext <mesh name>\n";
1758     return 0;
1759   }
1760
1761   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[ 1 ], di );
1762
1763   if ( aMesh.IsNull() )
1764   {
1765     di << "Mesh not found\n";
1766     return 0;
1767   }
1768
1769   Handle(AIS_InteractiveContext) anIC = ViewerTest::GetAISContext();
1770   if ( anIC.IsNull() )
1771   {
1772     di << "The context is null\n";
1773     return 0;
1774   }
1775
1776   // Prepare triangle labels
1777   MeshVS_DataMapOfIntegerAsciiString aLabels;
1778   Standard_Integer aLen = aMesh->GetDataSource()->GetAllElements().Extent();
1779   for ( Standard_Integer anIndex = 1; anIndex <= aLen; anIndex++ ){
1780     aLabels.Bind( anIndex, TCollection_AsciiString( anIndex ) );
1781   }
1782
1783   Handle(MeshVS_TextPrsBuilder) aTextBuilder = new MeshVS_TextPrsBuilder( aMesh.operator->(), 20., Quantity_NOC_YELLOW );
1784   aTextBuilder->SetTexts( Standard_True, aLabels );
1785   aMesh->AddBuilder( aTextBuilder );
1786
1787   return 0;
1788 }
1789
1790 static Standard_Integer meshdeform( Draw_Interpretor& di,
1791                                     Standard_Integer argc,
1792                                     const char** argv )
1793 {
1794   if ( argc < 3 )
1795   {
1796     di << "Wrong number of parameters\n";
1797     di << "Use : meshdeform <mesh name> < -mode {on|off} > [-scale scalefactor]\n";
1798     return 0;
1799   }
1800
1801   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[ 1 ], di );
1802
1803   if ( aMesh.IsNull() )
1804   {
1805     di << "Mesh not found\n";
1806     return 0;
1807   }
1808   Handle(AIS_InteractiveContext) anIC = ViewerTest::GetAISContext();
1809   if ( anIC.IsNull() )
1810   {
1811     di << "The context is null\n";
1812     return 0;
1813   }
1814
1815   TCollection_AsciiString aParam;
1816   TCollection_AsciiString aMode("off");
1817   Standard_Real           aScale(1.0);
1818
1819   for (Standard_Integer anIdx = 2; anIdx < argc; anIdx++)
1820   {
1821     if (!aParam.IsEmpty())
1822     {
1823       if (aParam == "-mode")
1824       {
1825         aMode = argv[anIdx];
1826       }
1827       else if (aParam == "-scale")
1828       {
1829         aScale = Draw::Atof(argv[anIdx]);
1830       }
1831       aParam.Clear();
1832     }
1833     else if (argv[anIdx][0] == '-')
1834     {
1835       aParam = argv[anIdx];
1836     }
1837   }
1838
1839   if(!aMode.IsEqual("on") && !aMode.IsEqual("off"))
1840   {
1841     di << "Wrong mode name\n";
1842     return 0;
1843   }
1844
1845   Handle ( MeshVS_DeformedDataSource ) aDefDS =
1846     new MeshVS_DeformedDataSource( aMesh->GetDataSource() , aScale );
1847
1848   const TColStd_PackedMapOfInteger& anAllIDs = aMesh->GetDataSource()->GetAllNodes();
1849
1850   Standard_Integer aNbNodes;
1851   MeshVS_EntityType aEntType;
1852
1853   TColStd_MapIteratorOfPackedMapOfInteger anIter( anAllIDs );
1854   for ( ; anIter.More(); anIter.Next() )
1855   {
1856     TColStd_Array1OfReal aCoords(1, 3);
1857     aMesh->GetDataSource()->GetGeom(anIter.Key(), Standard_False, aCoords, aNbNodes, aEntType);
1858
1859     gp_Vec aNorm = gp_Vec(aCoords.Value(1), aCoords.Value(2), aCoords.Value(3));
1860     if( !aNorm.Magnitude() )
1861       aNorm = gp_Vec(0,0,1);
1862     aDefDS->SetVector(anIter.Key(), aNorm.Normalized());
1863   }
1864
1865   aMesh->SetDataSource(aDefDS);
1866
1867   anIC->Redisplay (aMesh, Standard_False);
1868
1869   Handle( V3d_View ) aView = ViewerTest::CurrentView();
1870   if ( !aView.IsNull() )
1871     aView->FitAll();
1872
1873   return 0;
1874 }
1875
1876 static Standard_Integer mesh_edge_width( Draw_Interpretor& di,
1877                                         Standard_Integer argc,
1878                                         const char** argv )
1879 {
1880   try
1881   {
1882     OCC_CATCH_SIGNALS
1883       if ( argc < 3 )
1884       {
1885         di << "Wrong number of parameters\n";
1886         di << "Use : mesh_edge_width <mesh name> <width>\n";
1887         return 0;
1888       }
1889
1890       Handle(MeshVS_Mesh) aMesh = getMesh( argv[ 1 ], di );
1891       if ( aMesh.IsNull() )
1892       {
1893         di << "Mesh not found\n";
1894         return 0;
1895       }
1896
1897       const char* aWidthStr = argv[ 2 ];
1898       if ( aWidthStr == 0 || Draw::Atof( aWidthStr ) <= 0 )
1899       {
1900         di << "Width must be real value more than zero\n";
1901         return 0;
1902       }
1903
1904       double aWidth = Draw::Atof( aWidthStr );
1905
1906       Handle(AIS_InteractiveContext) anIC = ViewerTest::GetAISContext();
1907       if ( anIC.IsNull() )
1908       {
1909         di << "The context is null\n";
1910         return 0;
1911       }
1912
1913       Handle(MeshVS_Drawer) aDrawer = aMesh->GetDrawer();
1914       if ( aDrawer.IsNull() )
1915       {
1916         di << "The drawer is null\n";
1917         return 0;
1918       }
1919
1920       aDrawer->SetDouble( MeshVS_DA_EdgeWidth, aWidth );
1921       anIC->Redisplay (aMesh, Standard_True);
1922   }
1923   catch ( Standard_Failure const& )
1924   {
1925     di << "Error\n";
1926   }
1927
1928   return 0;
1929 }
1930
1931 //-----------------------------------------------------------------------------
1932
1933 static Standard_Integer meshinfo(Draw_Interpretor& di,
1934                                  Standard_Integer argc,
1935                                  const char** argv)
1936 {
1937   if ( argc != 2 )
1938   {
1939     di << "Wrong number of parameters. Use : meshinfo mesh\n";
1940     return 0;
1941   }
1942
1943   Handle(MeshVS_Mesh) aMesh = getMesh(argv[ 1 ], di);
1944   if ( aMesh.IsNull() )
1945   {
1946     di << "Mesh not found\n";
1947     return 0;
1948   }
1949
1950   Handle(XSDRAWSTLVRML_DataSource) stlMeshSource = Handle(XSDRAWSTLVRML_DataSource)::DownCast(aMesh->GetDataSource());
1951   if (!stlMeshSource.IsNull())
1952   {
1953     const TColStd_PackedMapOfInteger& nodes = stlMeshSource->GetAllNodes();
1954     const TColStd_PackedMapOfInteger& tris  = stlMeshSource->GetAllElements();
1955
1956     di << "Nb nodes = " << nodes.Extent() << "\n";
1957     di << "Nb triangles = " << tris.Extent() << "\n";
1958   }
1959
1960   return 0;
1961 }
1962
1963 //-----------------------------------------------------------------------------
1964
1965 void  XSDRAWSTLVRML::InitCommands (Draw_Interpretor& theCommands)
1966 {
1967   const char* g = "XSTEP-STL/VRML";  // Step transfer file commands
1968   //XSDRAW::LoadDraw(theCommands);
1969
1970   theCommands.Add ("ReadGltf",
1971                    "ReadGltf Doc file [-parallel {on|off}] [-listExternalFiles] [-noCreateDoc] [-doublePrecision {on|off}]"
1972                    "\n\t\t: Read glTF file into XDE document."
1973                    "\n\t\t:   -listExternalFiles do not read mesh and only list external files"
1974                    "\n\t\t:   -noCreateDoc read into existing XDE document"
1975                    "\n\t\t:   -doublePrecision store triangulation with double or single floating point"
1976                    "\n\t\t:                    precision (single by default)"
1977                    "\n\t\t:   -skipLateLoading data loading is skipped and can be performed later"
1978                    "\n\t\t:                    (false by default)"
1979                    "\n\t\t:   -keepLate data is loaded into itself with preservation of information"
1980                    "\n\t\t:             about deferred storage to load/unload this data later.",
1981                    "\n\t\t:   -toPrintDebugInfo print additional debug information during data reading"
1982                    __FILE__, ReadGltf, g);
1983   theCommands.Add ("readgltf",
1984                    "readgltf shape file"
1985                    "\n\t\t: Same as ReadGltf but reads glTF file into a shape instead of a document.",
1986                    __FILE__, ReadGltf, g);
1987   theCommands.Add ("WriteGltf",
1988                    "WriteGltf Doc file [-trsfFormat {compact|TRS|mat4}=compact]"
1989            "\n\t\t:                    [-comments Text] [-author Name]"
1990            "\n\t\t:                    [-forceUVExport] [-texturesSeparate]"
1991            "\n\t\t:                    [-nodeNameFormat {empty|product|instance|instOrProd|prodOrInst|prodAndInst|verbose}=instOrProd]"
1992            "\n\t\t:                    [-meshNameFormat {empty|product|instance|instOrProd|prodOrInst|prodAndInst|verbose}=product]"
1993            "\n\t\t: Write XDE document into glTF file."
1994            "\n\t\t:   -trsfFormat preferred transformation format"
1995            "\n\t\t:   -forceUVExport always export UV coordinates"
1996            "\n\t\t:   -texturesSeparate write textures to separate files"
1997            "\n\t\t:   -nodeNameFormat name format for Nodes"
1998            "\n\t\t:   -meshNameFormat name format for Meshes",
1999                    __FILE__, WriteGltf, g);
2000   theCommands.Add ("writegltf",
2001                    "writegltf shape file",
2002                    __FILE__, WriteGltf, g);
2003   theCommands.Add ("writevrml", "shape file [version VRML#1.0/VRML#2.0 (1/2): 2 by default] [representation shaded/wireframe/both (0/1/2): 1 by default]",__FILE__,writevrml,g);
2004   theCommands.Add ("writestl",  "shape file [ascii/binary (0/1) : 1 by default] [InParallel (0/1) : 0 by default]",__FILE__,writestl,g);
2005   theCommands.Add ("readstl",
2006                    "readstl shape file [-brep]"
2007                    "\n\t\t: Reads STL file and creates a new shape with specified name."
2008                    "\n\t\t: When -brep is specified, creates a Compound of per-triangle Faces."
2009                    "\n\t\t: Single triangulation-only Face is created otherwise (default).",
2010                    __FILE__, readstl, g);
2011   theCommands.Add ("loadvrml" , "shape file",__FILE__,loadvrml,g);
2012   theCommands.Add ("ReadObj",
2013                    "ReadObj Doc file [-fileCoordSys {Zup|Yup}] [-fileUnit Unit]"
2014            "\n\t\t:                  [-resultCoordSys {Zup|Yup}] [-singlePrecision]"
2015            "\n\t\t:                  [-listExternalFiles] [-noCreateDoc]"
2016            "\n\t\t: Read OBJ file into XDE document."
2017            "\n\t\t:   -fileUnit       length unit of OBJ file content;"
2018            "\n\t\t:   -fileCoordSys   coordinate system defined by OBJ file; Yup when not specified."
2019            "\n\t\t:   -resultCoordSys result coordinate system; Zup when not specified."
2020            "\n\t\t:   -singlePrecision truncate vertex data to single precision during read; FALSE by default."
2021            "\n\t\t:   -listExternalFiles do not read mesh and only list external files."
2022            "\n\t\t:   -noCreateDoc    read into existing XDE document.",
2023                    __FILE__, ReadObj, g);
2024   theCommands.Add ("readobj",
2025                    "readobj shape file [-fileCoordSys {Zup|Yup}] [-fileUnit Unit]"
2026            "\n\t\t:                    [-resultCoordSys {Zup|Yup}] [-singlePrecision]"
2027            "\n\t\t:                    [-singleFace]"
2028            "\n\t\t: Same as ReadObj but reads OBJ file into a shape instead of a document."
2029            "\n\t\t:   -singleFace merge OBJ content into a single triangulation Face.",
2030            __FILE__, ReadObj, g);
2031   theCommands.Add ("WriteObj",
2032                    "WriteObj Doc file [-fileCoordSys {Zup|Yup}] [-fileUnit Unit]"
2033            "\n\t\t:                   [-systemCoordSys {Zup|Yup}]"
2034            "\n\t\t:                   [-comments Text] [-author Name]"
2035            "\n\t\t: Write XDE document into OBJ file."
2036            "\n\t\t:   -fileUnit       length unit of OBJ file content;"
2037            "\n\t\t:   -fileCoordSys   coordinate system defined by OBJ file; Yup when not specified."
2038            "\n\t\t:   -systemCoordSys system coordinate system; Zup when not specified.",
2039                    __FILE__, WriteObj, g);
2040   theCommands.Add ("writeobj",
2041                    "writeobj shape file",
2042                    __FILE__, WriteObj, g);
2043
2044   theCommands.Add ("meshfromstl",     "creates MeshVS_Mesh from STL file",            __FILE__, createmesh,      g );
2045   theCommands.Add ("mesh3delem",      "creates 3d element mesh to test",              __FILE__, create3d,        g );
2046   theCommands.Add ("meshshadcolor",   "change MeshVS_Mesh shading color",             __FILE__, meshcolor,       g );
2047   theCommands.Add ("meshlinkcolor",   "change MeshVS_Mesh line color",                __FILE__, linecolor,       g );
2048   theCommands.Add ("meshmat",         "change MeshVS_Mesh material and transparency", __FILE__, meshmat,         g );
2049   theCommands.Add ("meshshrcoef",     "change MeshVS_Mesh shrink coeff",              __FILE__, shrink,          g );
2050   theCommands.Add ("meshclosed",      "meshclosed meshname (0/1) \nChange MeshVS_Mesh drawing mode. 0 - not closed object, 1 - closed object", __FILE__, closed, g);
2051   theCommands.Add ("meshshow",        "display MeshVS_Mesh object",                   __FILE__, mdisplay,        g );
2052   theCommands.Add ("meshhide",        "erase MeshVS_Mesh object",                     __FILE__, merase,          g );
2053   theCommands.Add ("meshhidesel",     "hide selected entities",                       __FILE__, hidesel,         g );
2054   theCommands.Add ("meshshowsel",     "show only selected entities",                  __FILE__, showonly,        g );
2055   theCommands.Add ("meshshowall",     "show all entities",                            __FILE__, showall,         g );
2056   theCommands.Add ("meshcolors",      "display color presentation",                   __FILE__, meshcolors,      g );
2057   theCommands.Add ("meshvectors",     "display sample vectors",                       __FILE__, meshvectors,     g );
2058   theCommands.Add ("meshtext",        "display text labels",                          __FILE__, meshtext,        g );
2059   theCommands.Add ("meshdeform",      "display deformed mesh",                        __FILE__, meshdeform,      g );
2060   theCommands.Add ("mesh_edge_width", "set width of edges",                           __FILE__, mesh_edge_width, g );
2061   theCommands.Add ("meshinfo",        "displays the number of nodes and triangles",   __FILE__, meshinfo,        g );
2062 }
2063
2064 //==============================================================================
2065 // XSDRAWSTLVRML::Factory
2066 //==============================================================================
2067 void XSDRAWSTLVRML::Factory(Draw_Interpretor& theDI)
2068 {
2069   XSDRAWIGES::InitSelect();
2070   XSDRAWIGES::InitToBRep(theDI);
2071   XSDRAWIGES::InitFromBRep(theDI);
2072   XSDRAWSTEP::InitCommands(theDI);
2073   XSDRAWSTLVRML::InitCommands(theDI);
2074   XSDRAW::LoadDraw(theDI);
2075 #ifdef OCCT_DEBUG
2076   theDI << "Draw Plugin : All TKXSDRAW commands are loaded\n";
2077 #endif
2078 }
2079
2080 // Declare entry point PLUGINFACTORY
2081 DPLUGIN(XSDRAWSTLVRML)
2082