0031080: Data Exchange, STL reader - improve API for reading multi-domain STL files
[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 #include <XSDRAWSTLVRML.hxx>
17
18 #include <AIS_InteractiveContext.hxx>
19 #include <Aspect_TypeOfMarker.hxx>
20 #include <Bnd_Box.hxx>
21 #include <BRep_Builder.hxx>
22 #include <BRepLib_PointCloudShape.hxx>
23 #include <DBRep.hxx>
24 #include <DDocStd.hxx>
25 #include <DDocStd_DrawDocument.hxx>
26 #include <Draw.hxx>
27 #include <Draw_Interpretor.hxx>
28 #include <Draw_PluginMacro.hxx>
29 #include <Draw_ProgressIndicator.hxx>
30 #include <Graphic3d_MaterialAspect.hxx>
31 #include <MeshVS_DataMapOfIntegerAsciiString.hxx>
32 #include <MeshVS_DeformedDataSource.hxx>
33 #include <MeshVS_Drawer.hxx>
34 #include <MeshVS_DrawerAttribute.hxx>
35 #include <MeshVS_ElementalColorPrsBuilder.hxx>
36 #include <MeshVS_Mesh.hxx>
37 #include <MeshVS_MeshEntityOwner.hxx>
38 #include <MeshVS_MeshPrsBuilder.hxx>
39 #include <MeshVS_NodalColorPrsBuilder.hxx>
40 #include <MeshVS_PrsBuilder.hxx>
41 #include <MeshVS_TextPrsBuilder.hxx>
42 #include <MeshVS_VectorPrsBuilder.hxx>
43 #include <OSD_Path.hxx>
44 #include <Quantity_Color.hxx>
45 #include <Quantity_HArray1OfColor.hxx>
46 #include <Quantity_NameOfColor.hxx>
47 #include <RWGltf_DracoParameters.hxx>
48 #include <RWGltf_CafReader.hxx>
49 #include <RWGltf_CafWriter.hxx>
50 #include <RWMesh_FaceIterator.hxx>
51 #include <RWStl.hxx>
52 #include <RWObj.hxx>
53 #include <RWObj_CafReader.hxx>
54 #include <RWObj_CafWriter.hxx>
55 #include <RWPly_CafWriter.hxx>
56 #include <RWPly_PlyWriterContext.hxx>
57 #include <SelectMgr_SelectionManager.hxx>
58 #include <Standard_ErrorHandler.hxx>
59 #include <StdSelect_ViewerSelector3d.hxx>
60 #include <StlAPI.hxx>
61 #include <StlAPI_Writer.hxx>
62 #include <TColgp_SequenceOfXYZ.hxx>
63 #include <TCollection_AsciiString.hxx>
64 #include <TColStd_Array1OfReal.hxx>
65 #include <TColStd_HPackedMapOfInteger.hxx>
66 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
67 #include <TDataStd_Name.hxx>
68 #include <TDocStd_Application.hxx>
69 #include <TDocStd_Document.hxx>
70 #include <TopoDS.hxx>
71 #include <TopoDS_Face.hxx>
72 #include <TopoDS_Shape.hxx>
73 #include <UnitsAPI.hxx>
74 #include <UnitsMethods.hxx>
75 #include <V3d_View.hxx>
76 #include <ViewerTest.hxx>
77 #include <VrmlAPI.hxx>
78 #include <VrmlAPI_Writer.hxx>
79 #include <VrmlData_DataMapOfShapeAppearance.hxx>
80 #include <VrmlData_Scene.hxx>
81 #include <VrmlData_ShapeConvert.hxx>
82 #include <XCAFDoc_DocumentTool.hxx>
83 #include <XCAFDoc_ShapeTool.hxx>
84 #include <XCAFPrs_DocumentExplorer.hxx>
85 #include <XSAlgo.hxx>
86 #include <XSAlgo_AlgoContainer.hxx>
87 #include <XSDRAW.hxx>
88 #include <XSDRAWIGES.hxx>
89 #include <XSDRAWSTEP.hxx>
90 #include <XSDRAWSTLVRML_DataSource.hxx>
91 #include <XSDRAWSTLVRML_DataSource3D.hxx>
92 #include <XSDRAWSTLVRML_DrawableMesh.hxx>
93
94 #ifndef _STDIO_H
95 #include <stdio.h>
96 #endif
97
98 extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
99                                            const Handle(AIS_InteractiveObject)& theAISObj,
100                                            Standard_Boolean theReplaceIfExists = Standard_True);
101
102 //! Parse RWMesh_NameFormat enumeration.
103 static bool parseNameFormat (const char* theArg,
104                              RWMesh_NameFormat& theFormat)
105 {
106   TCollection_AsciiString aName (theArg);
107   aName.LowerCase();
108   if (aName == "empty")
109   {
110     theFormat = RWMesh_NameFormat_Empty;
111   }
112   else if (aName == "product"
113         || aName == "prod")
114   {
115     theFormat = RWMesh_NameFormat_Product;
116   }
117   else if (aName == "instance"
118         || aName == "inst")
119   {
120     theFormat = RWMesh_NameFormat_Instance;
121   }
122   else if (aName == "instanceorproduct"
123         || aName == "instance||product"
124         || aName == "instance|product"
125         || aName == "instorprod"
126         || aName == "inst||prod"
127         || aName == "inst|prod")
128   {
129     theFormat = RWMesh_NameFormat_InstanceOrProduct;
130   }
131   else if (aName == "productorinstance"
132         || aName == "product||instance"
133         || aName == "product|instance"
134         || aName == "prodorinst"
135         || aName == "prod||inst"
136         || aName == "prod|inst")
137   {
138     theFormat = RWMesh_NameFormat_ProductOrInstance;
139   }
140   else if (aName == "productandinstance"
141         || aName == "prodandinst"
142         || aName == "product&instance"
143         || aName == "prod&inst")
144   {
145     theFormat = RWMesh_NameFormat_ProductAndInstance;
146   }
147   else if (aName == "productandinstanceandocaf"
148         || aName == "verbose"
149         || aName == "debug")
150   {
151     theFormat = RWMesh_NameFormat_ProductAndInstanceAndOcaf;
152   }
153   else
154   {
155     return false;
156   }
157   return true;
158 }
159
160 //! Parse RWMesh_CoordinateSystem enumeration.
161 static bool parseCoordinateSystem (const char* theArg,
162                                    RWMesh_CoordinateSystem& theSystem)
163 {
164   TCollection_AsciiString aCSStr (theArg);
165   aCSStr.LowerCase();
166   if (aCSStr == "zup")
167   {
168     theSystem = RWMesh_CoordinateSystem_Zup;
169   }
170   else if (aCSStr == "yup")
171   {
172     theSystem = RWMesh_CoordinateSystem_Yup;
173   }
174   else
175   {
176     return Standard_False;
177   }
178   return Standard_True;
179 }
180
181 //=============================================================================
182 //function : ReadGltf
183 //purpose  : Reads glTF file
184 //=============================================================================
185 static Standard_Integer ReadGltf (Draw_Interpretor& theDI,
186                                   Standard_Integer theNbArgs,
187                                   const char** theArgVec)
188 {
189   TCollection_AsciiString aDestName, aFilePath;
190   Standard_Boolean toUseExistingDoc = Standard_False;
191   Standard_Boolean toListExternalFiles = Standard_False;
192   Standard_Boolean isParallel = Standard_False;
193   Standard_Boolean isDoublePrec = Standard_False;
194   Standard_Boolean toSkipLateDataLoading = Standard_False;
195   Standard_Boolean toKeepLateData = Standard_True;
196   Standard_Boolean toPrintDebugInfo = Standard_False;
197   Standard_Boolean toLoadAllScenes = Standard_False;
198   Standard_Boolean toPrintAssetInfo = Standard_False;
199   Standard_Boolean isNoDoc = (TCollection_AsciiString(theArgVec[0]) == "readgltf");
200   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
201   {
202     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
203     anArgCase.LowerCase();
204     if (!isNoDoc
205      && (anArgCase == "-nocreate"
206       || anArgCase == "-nocreatedoc"))
207     {
208       toUseExistingDoc = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
209     }
210     else if (anArgCase == "-parallel")
211     {
212       isParallel = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
213     }
214     else if (anArgCase == "-doubleprec"
215           || anArgCase == "-doubleprecision"
216           || anArgCase == "-singleprec"
217           || anArgCase == "-singleprecision")
218     {
219       isDoublePrec = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
220       if (anArgCase.StartsWith ("-single"))
221       {
222         isDoublePrec = !isDoublePrec;
223       }
224     }
225     else if (anArgCase == "-skiplateloading")
226     {
227       toSkipLateDataLoading = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
228     }
229     else if (anArgCase == "-keeplate")
230     {
231       toKeepLateData = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
232     }
233     else if (anArgCase == "-allscenes")
234     {
235       toLoadAllScenes = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
236     }
237     else if (anArgCase == "-toprintinfo"
238           || anArgCase == "-toprintdebuginfo")
239     {
240       toPrintDebugInfo = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
241     }
242     else if (anArgCase == "-listexternalfiles"
243           || anArgCase == "-listexternals"
244           || anArgCase == "-listexternal"
245           || anArgCase == "-external"
246           || anArgCase == "-externalfiles")
247     {
248       toListExternalFiles = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
249     }
250     else if (anArgCase == "-assetinfo"
251           || anArgCase == "-metadata")
252     {
253       toPrintAssetInfo = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
254     }
255     else if (aDestName.IsEmpty())
256     {
257       aDestName = theArgVec[anArgIter];
258     }
259     else if (aFilePath.IsEmpty())
260     {
261       aFilePath = theArgVec[anArgIter];
262     }
263     else
264     {
265       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
266       return 1;
267     }
268   }
269   if (aFilePath.IsEmpty() && !aDestName.IsEmpty())
270   {
271     if (toListExternalFiles || toPrintAssetInfo)
272     {
273       std::swap (aFilePath, aDestName);
274     }
275   }
276   if (aFilePath.IsEmpty())
277   {
278     Message::SendFail() << "Syntax error: wrong number of arguments";
279     return 1;
280   }
281
282   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
283   Handle(TDocStd_Document) aDoc;
284   if (!aDestName.IsEmpty()
285    && !isNoDoc)
286   {
287     Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
288     Standard_CString aNameVar = aDestName.ToCString();
289     DDocStd::GetDocument (aNameVar, aDoc, Standard_False);
290     if (aDoc.IsNull())
291     {
292       if (toUseExistingDoc)
293       {
294         Message::SendFail() << "Error: document with name " << aDestName << " does not exist";
295         return 1;
296       }
297       anApp->NewDocument (TCollection_ExtendedString ("BinXCAF"), aDoc);
298     }
299     else if (!toUseExistingDoc)
300     {
301       Message::SendFail() << "Error: document with name " << aDestName << " already exists";
302       return 1;
303     }
304   }
305
306   Standard_Real aScaleFactorM = 1.;
307   if (!XCAFDoc_DocumentTool::GetLengthUnit(aDoc, aScaleFactorM, UnitsMethods_LengthUnit_Meter))
308   {
309     XSAlgo::AlgoContainer()->PrepareForTransfer(); // update unit info
310     aScaleFactorM = UnitsMethods::GetCasCadeLengthUnit(UnitsMethods_LengthUnit_Meter);
311   }
312
313   RWGltf_CafReader aReader;
314   aReader.SetSystemLengthUnit (aScaleFactorM);
315   aReader.SetSystemCoordinateSystem (RWMesh_CoordinateSystem_Zup);
316   aReader.SetDocument (aDoc);
317   aReader.SetParallel (isParallel);
318   aReader.SetDoublePrecision (isDoublePrec);
319   aReader.SetToSkipLateDataLoading (toSkipLateDataLoading);
320   aReader.SetToKeepLateData (toKeepLateData);
321   aReader.SetToPrintDebugMessages (toPrintDebugInfo);
322   aReader.SetLoadAllScenes (toLoadAllScenes);
323   if (aDestName.IsEmpty())
324   {
325     aReader.ProbeHeader (aFilePath);
326   }
327   else
328   {
329     aReader.Perform (aFilePath, aProgress->Start());
330     if (isNoDoc)
331     {
332       DBRep::Set (aDestName.ToCString(), aReader.SingleShape());
333     }
334     else
335     {
336       Handle(DDocStd_DrawDocument) aDrawDoc = new DDocStd_DrawDocument (aDoc);
337       TDataStd_Name::Set (aDoc->GetData()->Root(), aDestName);
338       Draw::Set (aDestName.ToCString(), aDrawDoc);
339     }
340   }
341
342   bool isFirstLine = true;
343   if (toPrintAssetInfo)
344   {
345     for (TColStd_IndexedDataMapOfStringString::Iterator aKeyIter (aReader.Metadata()); aKeyIter.More(); aKeyIter.Next())
346     {
347       if (!isFirstLine)
348       {
349         theDI << "\n";
350       }
351       isFirstLine = false;
352       theDI << aKeyIter.Key() << ": " << aKeyIter.Value();
353     }
354   }
355   if (toListExternalFiles)
356   {
357     if (!isFirstLine)
358     {
359       theDI << "\n";
360     }
361     for (NCollection_IndexedMap<TCollection_AsciiString>::Iterator aFileIter (aReader.ExternalFiles()); aFileIter.More(); aFileIter.Next())
362     {
363       theDI << "\"" << aFileIter.Value() << "\" ";
364     }
365   }
366
367   return 0;
368 }
369
370 //=============================================================================
371 //function : WriteGltf
372 //purpose  : Writes glTF file
373 //=============================================================================
374 static Standard_Integer WriteGltf (Draw_Interpretor& theDI,
375                                    Standard_Integer theNbArgs,
376                                    const char** theArgVec)
377 {
378   TCollection_AsciiString aGltfFilePath;
379   Handle(TDocStd_Document) aDoc;
380   Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
381   TColStd_IndexedDataMapOfStringString aFileInfo;
382   RWGltf_WriterTrsfFormat aTrsfFormat = RWGltf_WriterTrsfFormat_Compact;
383   RWMesh_CoordinateSystem aSystemCoordSys = RWMesh_CoordinateSystem_Zup;
384   bool toForceUVExport = false, toEmbedTexturesInGlb = true;
385   bool toMergeFaces = false, toSplitIndices16 = false;
386   RWMesh_NameFormat aNodeNameFormat = RWMesh_NameFormat_InstanceOrProduct;
387   RWMesh_NameFormat aMeshNameFormat = RWMesh_NameFormat_Product;
388   RWGltf_DracoParameters aDracoParameters;
389   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
390   {
391     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
392     anArgCase.LowerCase();
393     if (anArgCase == "-comments"
394      && anArgIter + 1 < theNbArgs)
395     {
396       aFileInfo.Add ("Comments", theArgVec[++anArgIter]);
397     }
398     else if (anArgCase == "-author"
399           && anArgIter + 1 < theNbArgs)
400     {
401       aFileInfo.Add ("Author", theArgVec[++anArgIter]);
402     }
403     else if (anArgCase == "-forceuvexport"
404           || anArgCase == "-forceuv")
405     {
406       toForceUVExport = true;
407       if (anArgIter + 1 < theNbArgs
408        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toForceUVExport))
409       {
410         ++anArgIter;
411       }
412     }
413     else if (anArgCase == "-mergefaces")
414     {
415       toMergeFaces = true;
416       if (anArgIter + 1 < theNbArgs
417        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toMergeFaces))
418       {
419         ++anArgIter;
420       }
421     }
422     else if (anArgCase == "-splitindices16"
423           || anArgCase == "-splitindexes16"
424           || anArgCase == "-splitindices"
425           || anArgCase == "-splitindexes"
426           || anArgCase == "-splitind")
427     {
428       toSplitIndices16 = true;
429       if (anArgIter + 1 < theNbArgs
430        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toSplitIndices16))
431       {
432         ++anArgIter;
433       }
434     }
435     else if (anArgIter + 1 < theNbArgs
436           && (anArgCase == "-systemcoordinatesystem"
437            || anArgCase == "-systemcoordsystem"
438            || anArgCase == "-systemcoordsys"
439            || anArgCase == "-syscoordsys"))
440     {
441       if (!parseCoordinateSystem (theArgVec[++anArgIter], aSystemCoordSys))
442       {
443         Message::SendFail() << "Syntax error: unknown coordinate system '" << theArgVec[anArgIter] << "'";
444         return 1;
445       }
446     }
447     else if (anArgCase == "-trsfformat"
448           && anArgIter + 1 < theNbArgs)
449     {
450       TCollection_AsciiString aTrsfStr (theArgVec[++anArgIter]);
451       aTrsfStr.LowerCase();
452       if (aTrsfStr == "compact")
453       {
454         aTrsfFormat = RWGltf_WriterTrsfFormat_Compact;
455       }
456       else if (aTrsfStr == "mat4")
457       {
458         aTrsfFormat = RWGltf_WriterTrsfFormat_Mat4;
459       }
460       else if (aTrsfStr == "trs")
461       {
462         aTrsfFormat = RWGltf_WriterTrsfFormat_TRS;
463       }
464       else
465       {
466         Message::SendFail() << "Syntax error at '" << anArgCase << "'";
467         return 1;
468       }
469     }
470     else if (anArgCase == "-nodenameformat"
471           || anArgCase == "-nodename")
472     {
473       ++anArgIter;
474       if (anArgIter >= theNbArgs
475       || !parseNameFormat (theArgVec[anArgIter], aNodeNameFormat))
476       {
477         Message::SendFail() << "Syntax error at '" << anArgCase << "'";
478         return 1;
479       }
480     }
481     else if (anArgCase == "-meshnameformat"
482           || anArgCase == "-meshname")
483     {
484       ++anArgIter;
485       if (anArgIter >= theNbArgs
486       || !parseNameFormat (theArgVec[anArgIter], aMeshNameFormat))
487       {
488         Message::SendFail() << "Syntax error at '" << anArgCase << "'";
489         return 1;
490       }
491     }
492     else if (aDoc.IsNull())
493     {
494       Standard_CString aNameVar = theArgVec[anArgIter];
495       DDocStd::GetDocument (aNameVar, aDoc, false);
496       if (aDoc.IsNull())
497       {
498         TopoDS_Shape aShape = DBRep::Get (aNameVar);
499         if (aShape.IsNull())
500         {
501           Message::SendFail() << "Syntax error: '" << aNameVar << "' is not a shape nor document";
502           return 1;
503         }
504
505         anApp->NewDocument (TCollection_ExtendedString ("BinXCAF"), aDoc);
506         Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (aDoc->Main());
507         // auto-naming doesn't generate meaningful instance names
508         //aShapeTool->SetAutoNaming (false);
509         aNodeNameFormat = RWMesh_NameFormat_Product;
510         aShapeTool->AddShape (aShape);
511       }
512     }
513     else if (aGltfFilePath.IsEmpty())
514     {
515       aGltfFilePath = theArgVec[anArgIter];
516     }
517     else if (anArgCase == "-texturesSeparate")
518     {
519       toEmbedTexturesInGlb = false;
520     }
521     else if (anArgCase == "-draco")
522     {
523       aDracoParameters.DracoCompression = Draw::ParseOnOffIterator(theNbArgs, theArgVec, anArgIter);
524     }
525     else if (anArgCase == "-compressionlevel" && (anArgIter + 1) < theNbArgs
526              && Draw::ParseInteger(theArgVec[anArgIter + 1], aDracoParameters.CompressionLevel))
527     {
528       ++anArgIter;
529     }
530     else if (anArgCase == "-quantizepositionbits" && (anArgIter + 1) < theNbArgs
531              && Draw::ParseInteger(theArgVec[anArgIter + 1], aDracoParameters.QuantizePositionBits))
532     {
533       ++anArgIter;
534     }
535     else if (anArgCase == "-quantizenormalbits" && (anArgIter + 1) < theNbArgs
536              && Draw::ParseInteger(theArgVec[anArgIter + 1], aDracoParameters.QuantizeNormalBits))
537     {
538       ++anArgIter;
539     }
540     else if (anArgCase == "-quantizetexcoordbits" && (anArgIter + 1) < theNbArgs
541              && Draw::ParseInteger(theArgVec[anArgIter + 1], aDracoParameters.QuantizeTexcoordBits))
542     {
543       ++anArgIter;
544     }
545     else if (anArgCase == "-quantizecolorbits" && (anArgIter + 1) < theNbArgs
546              && Draw::ParseInteger(theArgVec[anArgIter + 1], aDracoParameters.QuantizeColorBits))
547     {
548       ++anArgIter;
549     }
550     else if (anArgCase == "-quantizegenericbits" && (anArgIter + 1) < theNbArgs
551              && Draw::ParseInteger(theArgVec[anArgIter + 1], aDracoParameters.QuantizeGenericBits))
552     {
553       ++anArgIter;
554     }
555     else if (anArgCase == "-unifiedquantization")
556     {
557       aDracoParameters.UnifiedQuantization = Draw::ParseOnOffIterator(theNbArgs, theArgVec, anArgIter);
558     }
559     else
560     {
561       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
562       return 1;
563     }
564   }
565   if (aGltfFilePath.IsEmpty())
566   {
567     Message::SendFail() << "Syntax error: wrong number of arguments";
568     return 1;
569   }
570
571   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
572
573   TCollection_AsciiString anExt = aGltfFilePath;
574   anExt.LowerCase();
575   Standard_Real aScaleFactorM = 1.;
576   if (!XCAFDoc_DocumentTool::GetLengthUnit(aDoc, aScaleFactorM, UnitsMethods_LengthUnit_Meter))
577   {
578     XSAlgo::AlgoContainer()->PrepareForTransfer(); // update unit info
579     aScaleFactorM = UnitsMethods::GetCasCadeLengthUnit(UnitsMethods_LengthUnit_Meter);
580   }
581
582   RWGltf_CafWriter aWriter (aGltfFilePath, anExt.EndsWith (".glb"));
583   aWriter.SetTransformationFormat (aTrsfFormat);
584   aWriter.SetNodeNameFormat (aNodeNameFormat);
585   aWriter.SetMeshNameFormat (aMeshNameFormat);
586   aWriter.SetForcedUVExport (toForceUVExport);
587   aWriter.SetToEmbedTexturesInGlb (toEmbedTexturesInGlb);
588   aWriter.SetMergeFaces (toMergeFaces);
589   aWriter.SetSplitIndices16 (toSplitIndices16);
590   aWriter.SetCompressionParameters(aDracoParameters);
591   aWriter.ChangeCoordinateSystemConverter().SetInputLengthUnit (aScaleFactorM);
592   aWriter.ChangeCoordinateSystemConverter().SetInputCoordinateSystem (aSystemCoordSys);
593   aWriter.Perform (aDoc, aFileInfo, aProgress->Start());
594   return 0;
595 }
596
597 static Standard_Integer writestl
598 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
599 {
600   if (argc < 3 || argc > 4) {
601     di << "Use: " << argv[0]
602     << " shape file [ascii/binary (0/1) : 1 by default]\n";
603   } else {
604     TopoDS_Shape aShape = DBRep::Get(argv[1]);
605     Standard_Boolean isASCIIMode = Standard_False;
606     if (argc == 4) {
607       isASCIIMode = (Draw::Atoi(argv[3]) == 0);
608     }
609     StlAPI_Writer aWriter;
610     aWriter.ASCIIMode() = isASCIIMode;
611     Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (di);
612     Standard_Boolean isOK = aWriter.Write (aShape, argv[2], aProgress->Start());
613     if (!isOK)
614        di << "** Error **: Mesh writing has been failed.\n";
615   }
616   return 0;
617 }
618
619 //=============================================================================
620 //function : readstl
621 //purpose  : Reads stl file
622 //=============================================================================
623 static Standard_Integer readstl(Draw_Interpretor& theDI,
624                                 Standard_Integer theArgc,
625                                 const char** theArgv)
626 {
627   TCollection_AsciiString aShapeName, aFilePath;
628   bool toCreateCompOfTris = false;
629   bool anIsMulti = false;
630   double aMergeAngle = M_PI / 2.0;
631   for (Standard_Integer anArgIter = 1; anArgIter < theArgc; ++anArgIter)
632   {
633     TCollection_AsciiString anArg (theArgv[anArgIter]);
634     anArg.LowerCase();
635     if (aShapeName.IsEmpty())
636     {
637       aShapeName = theArgv[anArgIter];
638     }
639     else if (aFilePath.IsEmpty())
640     {
641       aFilePath = theArgv[anArgIter];
642     }
643     else if (anArg == "-brep")
644     {
645       toCreateCompOfTris = true;
646       if (anArgIter + 1 < theArgc
647        && Draw::ParseOnOff (theArgv[anArgIter + 1], toCreateCompOfTris))
648       {
649         ++anArgIter;
650       }
651     }
652     else if (anArg == "-multi")
653     {
654       anIsMulti = true;
655       if (anArgIter + 1 < theArgc
656        && Draw::ParseOnOff (theArgv[anArgIter + 1], anIsMulti))
657       {
658         ++anArgIter;
659       }
660     }
661     else if (anArg == "-mergeangle"
662           || anArg == "-smoothangle"
663           || anArg == "-nomergeangle"
664           || anArg == "-nosmoothangle")
665     {
666       if (anArg.StartsWith ("-no"))
667       {
668         aMergeAngle = M_PI / 2.0;
669       }
670       else
671       {
672         aMergeAngle = M_PI / 4.0;
673         if (anArgIter + 1 < theArgc
674          && Draw::ParseReal (theArgv[anArgIter + 1], aMergeAngle))
675         {
676           if (aMergeAngle < 0.0 || aMergeAngle > 90.0)
677           {
678             theDI << "Syntax error: angle should be within [0,90] range";
679             return 1;
680           }
681
682           ++anArgIter;
683           aMergeAngle = aMergeAngle * M_PI / 180.0;
684         }
685       }
686     }
687     else
688     {
689       Message::SendFail() << "Syntax error: unknown argument '" << theArgv[anArgIter] << "'";
690       return 1;
691     }
692   }
693   if (aFilePath.IsEmpty())
694   {
695     Message::SendFail() << "Syntax error: not enough arguments";
696     return 1;
697   }
698
699   TopoDS_Shape aShape;
700   if (!toCreateCompOfTris)
701   {
702     Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI,1);
703     if(anIsMulti)
704     {
705       NCollection_Sequence<Handle(Poly_Triangulation)> aTriangList;
706       // Read STL file to the triangulation list.
707       RWStl::ReadFile(aFilePath.ToCString(),aMergeAngle,aTriangList,aProgress->Start());
708       BRep_Builder aB;
709       TopoDS_Face aFace;
710       if (aTriangList.Size() == 1)
711       {
712         aB.MakeFace (aFace);
713         aB.UpdateFace (aFace,aTriangList.First());
714         aShape = aFace;
715       }
716       else
717       {
718         TopoDS_Compound aCmp;
719         aB.MakeCompound (aCmp);
720       
721         NCollection_Sequence<Handle(Poly_Triangulation)>::Iterator anIt (aTriangList);
722         for (; anIt.More(); anIt.Next())
723         { 
724           aB.MakeFace (aFace);
725           aB.UpdateFace (aFace,anIt.Value());
726           aB.Add (aCmp,aFace);
727         }
728         aShape = aCmp;
729       }
730     }
731     else
732     {
733       // Read STL file to the triangulation.
734       Handle(Poly_Triangulation) aTriangulation = RWStl::ReadFile (aFilePath.ToCString(),aMergeAngle,aProgress->Start());
735
736       TopoDS_Face aFace;
737       BRep_Builder aB;
738       aB.MakeFace (aFace);
739       aB.UpdateFace (aFace,aTriangulation);
740       aShape = aFace;
741     }
742   }
743   else
744   {
745     Standard_DISABLE_DEPRECATION_WARNINGS
746     StlAPI::Read(aShape, aFilePath.ToCString());
747     Standard_ENABLE_DEPRECATION_WARNINGS
748   }
749   DBRep::Set (aShapeName.ToCString(), aShape);
750   return 0;
751 }
752
753 //=============================================================================
754 //function : ReadObj
755 //purpose  : Reads OBJ file
756 //=============================================================================
757 static Standard_Integer ReadObj (Draw_Interpretor& theDI,
758                                  Standard_Integer theNbArgs,
759                                  const char** theArgVec)
760 {
761   TCollection_AsciiString aDestName, aFilePath;
762   Standard_Boolean toUseExistingDoc = Standard_False;
763   Standard_Real aFileUnitFactor = -1.0;
764   RWMesh_CoordinateSystem aResultCoordSys = RWMesh_CoordinateSystem_Zup, aFileCoordSys = RWMesh_CoordinateSystem_Yup;
765   Standard_Boolean toListExternalFiles = Standard_False, isSingleFace = Standard_False, isSinglePrecision = Standard_False;
766   Standard_Boolean isNoDoc = (TCollection_AsciiString(theArgVec[0]) == "readobj");
767   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
768   {
769     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
770     anArgCase.LowerCase();
771     if (anArgIter + 1 < theNbArgs
772      && (anArgCase == "-unit"
773       || anArgCase == "-units"
774       || anArgCase == "-fileunit"
775       || anArgCase == "-fileunits"))
776     {
777       const TCollection_AsciiString aUnitStr (theArgVec[++anArgIter]);
778       aFileUnitFactor = UnitsAPI::AnyToSI (1.0, aUnitStr.ToCString());
779       if (aFileUnitFactor <= 0.0)
780       {
781         Message::SendFail() << "Syntax error: wrong length unit '" << aUnitStr << "'";
782         return 1;
783       }
784     }
785     else if (anArgIter + 1 < theNbArgs
786           && (anArgCase == "-filecoordinatesystem"
787            || anArgCase == "-filecoordsystem"
788            || anArgCase == "-filecoordsys"))
789     {
790       if (!parseCoordinateSystem (theArgVec[++anArgIter], aFileCoordSys))
791       {
792         Message::SendFail() << "Syntax error: unknown coordinate system '" << theArgVec[anArgIter] << "'";
793         return 1;
794       }
795     }
796     else if (anArgIter + 1 < theNbArgs
797           && (anArgCase == "-resultcoordinatesystem"
798            || anArgCase == "-resultcoordsystem"
799            || anArgCase == "-resultcoordsys"
800            || anArgCase == "-rescoordsys"))
801     {
802       if (!parseCoordinateSystem (theArgVec[++anArgIter], aResultCoordSys))
803       {
804         Message::SendFail() << "Syntax error: unknown coordinate system '" << theArgVec[anArgIter] << "'";
805         return 1;
806       }
807     }
808     else if (anArgCase == "-singleprecision"
809           || anArgCase == "-singleprec")
810     {
811       isSinglePrecision = Standard_True;
812       if (anArgIter + 1 < theNbArgs
813        && Draw::ParseOnOff (theArgVec[anArgIter + 1], isSinglePrecision))
814       {
815         ++anArgIter;
816       }
817     }
818     else if (isNoDoc
819           && (anArgCase == "-singleface"
820            || anArgCase == "-singletriangulation"))
821     {
822       isSingleFace = Standard_True;
823     }
824     else if (!isNoDoc
825           && (anArgCase == "-nocreate"
826            || anArgCase == "-nocreatedoc"))
827     {
828       toUseExistingDoc = Standard_True;
829       if (anArgIter + 1 < theNbArgs
830        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toUseExistingDoc))
831       {
832         ++anArgIter;
833       }
834     }
835     else if (anArgCase == "-listexternalfiles"
836           || anArgCase == "-listexternals"
837           || anArgCase == "-listexternal"
838           || anArgCase == "-external"
839           || anArgCase == "-externalfiles")
840     {
841       toListExternalFiles = Standard_True;
842     }
843     else if (aDestName.IsEmpty())
844     {
845       aDestName = theArgVec[anArgIter];
846     }
847     else if (aFilePath.IsEmpty())
848     {
849       aFilePath = theArgVec[anArgIter];
850     }
851     else
852     {
853       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
854       return 1;
855     }
856   }
857   if (aFilePath.IsEmpty())
858   {
859     Message::SendFail() << "Syntax error: wrong number of arguments";
860     return 1;
861   }
862
863   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
864   Handle(TDocStd_Document) aDoc;
865   if (!isNoDoc
866    && !toListExternalFiles)
867   {
868     Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
869     Standard_CString aNameVar = aDestName.ToCString();
870     DDocStd::GetDocument (aNameVar, aDoc, Standard_False);
871     if (aDoc.IsNull())
872     {
873       if (toUseExistingDoc)
874       {
875         Message::SendFail() << "Error: document with name " << aDestName << " does not exist";
876         return 1;
877       }
878       anApp->NewDocument (TCollection_ExtendedString ("BinXCAF"), aDoc);
879     }
880     else if (!toUseExistingDoc)
881     {
882       Message::SendFail() << "Error: document with name " << aDestName << " already exists";
883       return 1;
884     }
885   }
886   Standard_Real aScaleFactorM = 1.;
887   if (!XCAFDoc_DocumentTool::GetLengthUnit(aDoc, aScaleFactorM, UnitsMethods_LengthUnit_Meter))
888   {
889     XSAlgo::AlgoContainer()->PrepareForTransfer(); // update unit info
890     aScaleFactorM = UnitsMethods::GetCasCadeLengthUnit(UnitsMethods_LengthUnit_Meter);
891   }
892
893   RWObj_CafReader aReader;
894   aReader.SetSinglePrecision (isSinglePrecision);
895   aReader.SetSystemLengthUnit (aScaleFactorM);
896   aReader.SetSystemCoordinateSystem (aResultCoordSys);
897   aReader.SetFileLengthUnit (aFileUnitFactor);
898   aReader.SetFileCoordinateSystem (aFileCoordSys);
899   aReader.SetDocument (aDoc);
900   if (isSingleFace)
901   {
902     RWObj_TriangulationReader aSimpleReader;
903     aSimpleReader.SetSinglePrecision (isSinglePrecision);
904     aSimpleReader.SetCreateShapes (Standard_False);
905     aSimpleReader.SetTransformation (aReader.CoordinateSystemConverter());
906     aSimpleReader.Read (aFilePath.ToCString(), aProgress->Start());
907
908     Handle(Poly_Triangulation) aTriangulation = aSimpleReader.GetTriangulation();
909     TopoDS_Face aFace;
910     BRep_Builder aBuiler;
911     aBuiler.MakeFace (aFace);
912     aBuiler.UpdateFace (aFace, aTriangulation);
913     DBRep::Set (aDestName.ToCString(), aFace);
914     return 0;
915   }
916
917   if (toListExternalFiles)
918   {
919     aReader.ProbeHeader (aFilePath);
920     for (NCollection_IndexedMap<TCollection_AsciiString>::Iterator aFileIter (aReader.ExternalFiles()); aFileIter.More(); aFileIter.Next())
921     {
922       theDI << "\"" << aFileIter.Value() << "\" ";
923     }
924   }
925   else
926   {
927     aReader.Perform (aFilePath, aProgress->Start());
928     if (isNoDoc)
929     {
930       DBRep::Set (aDestName.ToCString(), aReader.SingleShape());
931     }
932     else
933     {
934       Handle(DDocStd_DrawDocument) aDrawDoc = new DDocStd_DrawDocument (aDoc);
935       TDataStd_Name::Set (aDoc->GetData()->Root(), aDestName);
936       Draw::Set (aDestName.ToCString(), aDrawDoc);
937     }
938   }
939   return 0;
940 }
941
942 //=============================================================================
943 //function : WriteObj
944 //purpose  : Writes OBJ file
945 //=============================================================================
946 static Standard_Integer WriteObj (Draw_Interpretor& theDI,
947                                   Standard_Integer theNbArgs,
948                                   const char** theArgVec)
949 {
950   TCollection_AsciiString anObjFilePath;
951   Handle(TDocStd_Document) aDoc;
952   Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
953   TColStd_IndexedDataMapOfStringString aFileInfo;
954   Standard_Real aFileUnitFactor = -1.0;
955   RWMesh_CoordinateSystem aSystemCoordSys = RWMesh_CoordinateSystem_Zup, aFileCoordSys = RWMesh_CoordinateSystem_Yup;
956   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
957   {
958     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
959     anArgCase.LowerCase();
960         if (anArgIter + 1 < theNbArgs
961      && (anArgCase == "-unit"
962       || anArgCase == "-units"
963       || anArgCase == "-fileunit"
964       || anArgCase == "-fileunits"))
965     {
966       const TCollection_AsciiString aUnitStr (theArgVec[++anArgIter]);
967       aFileUnitFactor = UnitsAPI::AnyToSI (1.0, aUnitStr.ToCString());
968       if (aFileUnitFactor <= 0.0)
969       {
970         Message::SendFail() << "Syntax error: wrong length unit '" << aUnitStr << "'";
971         return 1;
972       }
973     }
974     else if (anArgIter + 1 < theNbArgs
975           && (anArgCase == "-filecoordinatesystem"
976            || anArgCase == "-filecoordsystem"
977            || anArgCase == "-filecoordsys"))
978     {
979       if (!parseCoordinateSystem (theArgVec[++anArgIter], aFileCoordSys))
980       {
981         Message::SendFail() << "Syntax error: unknown coordinate system '" << theArgVec[anArgIter] << "'";
982         return 1;
983       }
984     }
985     else if (anArgIter + 1 < theNbArgs
986           && (anArgCase == "-systemcoordinatesystem"
987            || anArgCase == "-systemcoordsystem"
988            || anArgCase == "-systemcoordsys"
989            || anArgCase == "-syscoordsys"))
990     {
991       if (!parseCoordinateSystem (theArgVec[++anArgIter], aSystemCoordSys))
992       {
993         Message::SendFail() << "Syntax error: unknown coordinate system '" << theArgVec[anArgIter] << "'";
994         return 1;
995       }
996     }
997     else if (anArgCase == "-comments"
998           && anArgIter + 1 < theNbArgs)
999     {
1000       aFileInfo.Add ("Comments", theArgVec[++anArgIter]);
1001     }
1002     else if (anArgCase == "-author"
1003           && anArgIter + 1 < theNbArgs)
1004     {
1005       aFileInfo.Add ("Author", theArgVec[++anArgIter]);
1006     }
1007     else if (aDoc.IsNull())
1008     {
1009       Standard_CString aNameVar = theArgVec[anArgIter];
1010       DDocStd::GetDocument (aNameVar, aDoc, false);
1011       if (aDoc.IsNull())
1012       {
1013         TopoDS_Shape aShape = DBRep::Get (aNameVar);
1014         if (aShape.IsNull())
1015         {
1016           Message::SendFail() << "Syntax error: '" << aNameVar << "' is not a shape nor document";
1017           return 1;
1018         }
1019
1020         anApp->NewDocument (TCollection_ExtendedString ("BinXCAF"), aDoc);
1021         Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (aDoc->Main());
1022         aShapeTool->AddShape (aShape);
1023       }
1024     }
1025     else if (anObjFilePath.IsEmpty())
1026     {
1027       anObjFilePath = theArgVec[anArgIter];
1028     }
1029     else
1030     {
1031       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
1032       return 1;
1033     }
1034   }
1035   if (anObjFilePath.IsEmpty())
1036   {
1037     Message::SendFail() << "Syntax error: wrong number of arguments";
1038     return 1;
1039   }
1040
1041   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
1042
1043   const Standard_Real aSystemUnitFactor = UnitsMethods::GetCasCadeLengthUnit() * 0.001;
1044   RWObj_CafWriter aWriter (anObjFilePath);
1045   aWriter.ChangeCoordinateSystemConverter().SetInputLengthUnit (aSystemUnitFactor);
1046   aWriter.ChangeCoordinateSystemConverter().SetInputCoordinateSystem (aSystemCoordSys);
1047   aWriter.ChangeCoordinateSystemConverter().SetOutputLengthUnit (aFileUnitFactor);
1048   aWriter.ChangeCoordinateSystemConverter().SetOutputCoordinateSystem (aFileCoordSys);
1049   aWriter.Perform (aDoc, aFileInfo, aProgress->Start());
1050   return 0;
1051 }
1052
1053 static Standard_Integer writevrml
1054 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1055 {
1056   if (argc < 3 || argc > 5) 
1057   {
1058     di << "wrong number of parameters\n";
1059     return 0;
1060   }
1061
1062   TopoDS_Shape aShape = DBRep::Get(argv[1]);
1063
1064   // Get the optional parameters
1065   Standard_Integer aVersion = 2;
1066   Standard_Integer aType = 1;
1067   if (argc >= 4)
1068   {
1069     aVersion = Draw::Atoi(argv[3]);
1070     if (argc == 5)
1071       aType = Draw::Atoi(argv[4]);
1072   }
1073
1074   // Bound parameters
1075   aVersion = Max(1, aVersion);
1076   aVersion = Min(2, aVersion);
1077   aType = Max(0, aType);
1078   aType = Min(2, aType);
1079
1080   VrmlAPI_Writer writer;
1081
1082   switch (aType)
1083   {
1084   case 0: writer.SetRepresentation(VrmlAPI_ShadedRepresentation); break;
1085   case 1: writer.SetRepresentation(VrmlAPI_WireFrameRepresentation); break;
1086   case 2: writer.SetRepresentation(VrmlAPI_BothRepresentation); break;
1087   }
1088
1089   if (!writer.Write(aShape, argv[2], aVersion))
1090   {
1091     di << "Error: File " << argv[2] << " was not written\n";
1092   }
1093
1094   return 0;
1095 }
1096
1097 //=======================================================================
1098 //function : loadvrml
1099 //purpose  :
1100 //=======================================================================
1101
1102 static Standard_Integer loadvrml
1103 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1104 {
1105   if (argc<3) di << "wrong number of parameters"    << "\n";
1106   else {
1107     TopoDS_Shape aShape ;
1108     VrmlData_DataMapOfShapeAppearance aShapeAppMap;
1109
1110     //-----------------------------------------------------------
1111     std::filebuf aFic;
1112     std::istream aStream (&aFic);
1113
1114     if (aFic.open(argv[2], std::ios::in)) {
1115
1116       // Get path of the VRML file.
1117       OSD_Path aPath(argv[2]);
1118       TCollection_AsciiString aVrmlDir(".");
1119       TCollection_AsciiString aDisk = aPath.Disk();
1120       TCollection_AsciiString aTrek = aPath.Trek();
1121       if (!aTrek.IsEmpty())
1122       {
1123         if (!aDisk.IsEmpty())
1124           aVrmlDir = aDisk;
1125         else
1126           aVrmlDir.Clear();
1127         aTrek.ChangeAll('|', '/');
1128         aVrmlDir += aTrek;
1129       }
1130
1131       VrmlData_Scene aScene;
1132       XSAlgo::AlgoContainer()->PrepareForTransfer(); // update unit info
1133       Standard_Real anOCCUnitMM = UnitsMethods::GetCasCadeLengthUnit();
1134       aScene.SetLinearScale(1000. / anOCCUnitMM);
1135
1136       aScene.SetVrmlDir (aVrmlDir);
1137       aScene << aStream;
1138       const char * aStr = 0L;
1139       switch (aScene.Status()) {
1140
1141       case VrmlData_StatusOK:
1142         {
1143           aShape = aScene.GetShape(aShapeAppMap);
1144           break;
1145         }
1146       case VrmlData_EmptyData:            aStr = "EmptyData"; break;
1147       case VrmlData_UnrecoverableError:   aStr = "UnrecoverableError"; break;
1148       case VrmlData_GeneralError:         aStr = "GeneralError"; break;
1149       case VrmlData_EndOfFile:            aStr = "EndOfFile"; break;
1150       case VrmlData_NotVrmlFile:          aStr = "NotVrmlFile"; break;
1151       case VrmlData_CannotOpenFile:       aStr = "CannotOpenFile"; break;
1152       case VrmlData_VrmlFormatError:      aStr = "VrmlFormatError"; break;
1153       case VrmlData_NumericInputError:    aStr = "NumericInputError"; break;
1154       case VrmlData_IrrelevantNumber:     aStr = "IrrelevantNumber"; break;
1155       case VrmlData_BooleanInputError:    aStr = "BooleanInputError"; break;
1156       case VrmlData_StringInputError:     aStr = "StringInputError"; break;
1157       case VrmlData_NodeNameUnknown:      aStr = "NodeNameUnknown"; break;
1158       case VrmlData_NonPositiveSize:      aStr = "NonPositiveSize"; break;
1159       case VrmlData_ReadUnknownNode:      aStr = "ReadUnknownNode"; break;
1160       case VrmlData_NonSupportedFeature:  aStr = "NonSupportedFeature"; break;
1161       case VrmlData_OutputStreamUndefined:aStr = "OutputStreamUndefined"; break;
1162       case VrmlData_NotImplemented:       aStr = "NotImplemented"; break;
1163       default:
1164         break;
1165       }
1166       if (aStr) {
1167         di << " ++ VRML Error: " << aStr << " in line "
1168           << aScene.GetLineError() << "\n";
1169       }
1170       else {
1171         DBRep::Set(argv[1],aShape);
1172       }
1173     }
1174     else {
1175       di << "cannot open file\n";
1176     }
1177
1178
1179     //-----------------------------------------------------------
1180   }
1181   return 0;
1182 }
1183
1184 //-----------------------------------------------------------------------------
1185 static Standard_Integer createmesh
1186 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1187 {
1188   if (argc<3)
1189   {
1190     di << "Wrong number of parameters\n";
1191     di << "Use: " << argv[0] << " <mesh name> <stl file>\n";
1192     return 0;
1193   }
1194
1195   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1196   if (aContext.IsNull())
1197   {
1198     di << "No active view. Please call 'vinit' first\n";
1199     return 0;
1200   }
1201
1202   // Progress indicator
1203   OSD_Path aFile( argv[2] );
1204   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (di, 1);
1205   Handle(Poly_Triangulation) aSTLMesh = RWStl::ReadFile (aFile, aProgress->Start());
1206
1207   di << "Reading OK...\n";
1208   Handle( XSDRAWSTLVRML_DataSource ) aDS = new XSDRAWSTLVRML_DataSource( aSTLMesh );
1209   di << "Data source is created successful\n";
1210   Handle( MeshVS_Mesh ) aMesh = new MeshVS_Mesh();
1211   di << "MeshVS_Mesh is created successful\n";
1212
1213   aMesh->SetDataSource( aDS );
1214   aMesh->AddBuilder( new MeshVS_MeshPrsBuilder( aMesh.operator->() ), Standard_True );
1215
1216   aMesh->GetDrawer()->SetColor( MeshVS_DA_EdgeColor, Quantity_NOC_YELLOW );
1217
1218   // Hide all nodes by default
1219   Handle(TColStd_HPackedMapOfInteger) aNodes = new TColStd_HPackedMapOfInteger();
1220   const Standard_Integer aLen = aSTLMesh->NbNodes();
1221   for ( Standard_Integer anIndex = 1; anIndex <= aLen; anIndex++ )
1222     aNodes->ChangeMap().Add( anIndex );
1223   aMesh->SetHiddenNodes( aNodes );
1224   aMesh->SetSelectableNodes ( aNodes );
1225
1226   VDisplayAISObject(argv[1], aMesh);
1227   aContext->Deactivate( aMesh );
1228
1229   Draw::Set( argv[1], new XSDRAWSTLVRML_DrawableMesh( aMesh ) );
1230   Handle( V3d_View ) aView = ViewerTest::CurrentView();
1231   if ( !aView.IsNull() )
1232     aView->FitAll();
1233
1234   return 0;
1235 }
1236 //-----------------------------------------------------------------------------
1237
1238 static Standard_Integer create3d
1239 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1240 {
1241   if (argc<2)
1242   {
1243     di << "Wrong number of parameters\n";
1244     di << "Use: " << argv[0] << " <mesh name>\n";
1245     return 0;
1246   }
1247
1248   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1249   if (aContext.IsNull())
1250   {
1251     di << "No active view. Please call 'vinit' first\n";
1252     return 0;
1253   }
1254
1255   Handle( XSDRAWSTLVRML_DataSource3D ) aDS = new XSDRAWSTLVRML_DataSource3D();
1256   di << "Data source is created successful\n";
1257   Handle( MeshVS_Mesh ) aMesh = new MeshVS_Mesh();
1258   di << "MeshVS_Mesh is created successful\n";
1259
1260   aMesh->SetDataSource( aDS );
1261   aMesh->AddBuilder( new MeshVS_MeshPrsBuilder( aMesh.operator->() ), Standard_True );
1262
1263   aMesh->GetDrawer()->SetColor( MeshVS_DA_EdgeColor, Quantity_NOC_YELLOW );
1264
1265   // Hide all nodes by default
1266   Handle(TColStd_HPackedMapOfInteger) aNodes = new TColStd_HPackedMapOfInteger();
1267   Standard_Integer aLen = aDS->GetAllNodes().Extent();
1268   for ( Standard_Integer anIndex = 1; anIndex <= aLen; anIndex++ )
1269     aNodes->ChangeMap().Add( anIndex );
1270   aMesh->SetHiddenNodes( aNodes );
1271   aMesh->SetSelectableNodes ( aNodes );
1272
1273   VDisplayAISObject(argv[1], aMesh);
1274   aContext->Deactivate( aMesh );
1275
1276   Draw::Set( argv[1], new XSDRAWSTLVRML_DrawableMesh( aMesh ) );
1277   Handle( V3d_View ) aView = ViewerTest::CurrentView();
1278   if ( !aView.IsNull() )
1279     aView->FitAll();
1280
1281   return 0;
1282 }
1283
1284 Handle( MeshVS_Mesh ) getMesh( const char* theName, Draw_Interpretor& di)
1285 {
1286   Handle( XSDRAWSTLVRML_DrawableMesh ) aDrawMesh =
1287     Handle( XSDRAWSTLVRML_DrawableMesh )::DownCast( Draw::Get( theName ) );
1288
1289   if( aDrawMesh.IsNull() )
1290   {
1291     di << "There is no such object\n";
1292     return NULL;
1293   }
1294   else
1295   {
1296     Handle( MeshVS_Mesh ) aMesh = aDrawMesh->GetMesh();
1297     if( aMesh.IsNull() )
1298     {
1299       di << "There is invalid mesh\n";
1300       return NULL;
1301     }
1302     else
1303       return aMesh;
1304   }
1305 }
1306
1307 //-----------------------------------------------------------------------------
1308 static Standard_Integer setcolor
1309 (Draw_Interpretor& di, Standard_Integer argc, const char** argv, Standard_Integer theParam )
1310 {
1311   if (argc<5)
1312     di << "Wrong number of parameters\n";
1313   else
1314   {
1315     Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1316     if( !aMesh.IsNull() )
1317     {
1318       Standard_Real aRed = Draw::Atof (argv[2]);
1319       Standard_Real aGreen = Draw::Atof (argv[3]);
1320       Standard_Real aBlue = Draw::Atof (argv[4]);
1321       aMesh->GetDrawer()->SetColor( (MeshVS_DrawerAttribute)theParam,
1322                                     Quantity_Color( aRed, aGreen, aBlue, Quantity_TOC_RGB ) );
1323
1324       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1325
1326       if( aContext.IsNull() )
1327         di << "The context is null\n";
1328       else
1329         aContext->Redisplay (aMesh, Standard_True);
1330     }
1331   }
1332   return 0;
1333 }
1334 //-----------------------------------------------------------------------------
1335 static Standard_Integer meshcolor
1336 (Draw_Interpretor& theInterp, Standard_Integer argc, const char** argv )
1337 {
1338   return setcolor( theInterp, argc, argv, MeshVS_DA_InteriorColor );
1339 }
1340 //-----------------------------------------------------------------------------
1341 static Standard_Integer linecolor
1342 (Draw_Interpretor& theInterp, Standard_Integer argc, const char** argv )
1343 {
1344   return setcolor( theInterp, argc, argv, MeshVS_DA_EdgeColor );
1345 }
1346 //-----------------------------------------------------------------------------
1347 static Standard_Integer meshmat
1348 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1349 {
1350   if (argc<3)
1351     di << "Wrong number of parameters\n";
1352   else
1353   {
1354     Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1355     if( !aMesh.IsNull() )
1356     {
1357       Standard_Integer aMaterial = Draw::Atoi (argv[2]);
1358
1359       Graphic3d_MaterialAspect aMatAsp =
1360         (Graphic3d_MaterialAspect)(Graphic3d_NameOfMaterial)aMaterial;
1361
1362       if (argc == 4)
1363       {
1364         Standard_Real aTransparency = Draw::Atof(argv[3]);
1365         aMatAsp.SetTransparency (Standard_ShortReal (aTransparency));
1366       }
1367       aMesh->GetDrawer()->SetMaterial( MeshVS_DA_FrontMaterial, aMatAsp );
1368       aMesh->GetDrawer()->SetMaterial( MeshVS_DA_BackMaterial, aMatAsp );
1369
1370       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1371
1372       if( aContext.IsNull() )
1373         di << "The context is null\n";
1374       else
1375         aContext->Redisplay (aMesh, Standard_True);
1376     }
1377   }
1378   return 0;
1379 }
1380 //-----------------------------------------------------------------------------
1381 static Standard_Integer shrink
1382 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1383 {
1384   if (argc<3)
1385     di << "Wrong number of parameters\n";
1386   else
1387   {
1388     Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1389     if( !aMesh.IsNull() )
1390     {
1391       Standard_Real aShrinkCoeff = Draw::Atof (argv[2]);
1392       aMesh->GetDrawer()->SetDouble( MeshVS_DA_ShrinkCoeff, aShrinkCoeff );
1393
1394       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1395
1396       if( aContext.IsNull() )
1397         di << "The context is null\n";
1398       else
1399         aContext->Redisplay (aMesh, Standard_True);
1400     }
1401   }
1402   return 0;
1403 }
1404
1405 //-----------------------------------------------------------------------------
1406 static Standard_Integer closed (Draw_Interpretor& theDI, Standard_Integer theArgc, const char** theArgv)
1407 {
1408   if (theArgc < 3)
1409   {
1410     theDI << "Wrong number of parameters.\n";
1411   }
1412   else
1413   {
1414     Handle(MeshVS_Mesh) aMesh = getMesh (theArgv[1], theDI);
1415     if (!aMesh.IsNull())
1416     {
1417       Standard_Boolean aFlag = Draw::Atoi (theArgv[2]) != 0;
1418       aMesh->GetDrawer()->SetBoolean (MeshVS_DA_SupressBackFaces, aFlag);
1419
1420       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1421       if (aContext.IsNull())
1422       {
1423         theDI << "The context is null\n";
1424       }
1425       else
1426       {
1427         aContext->Redisplay (aMesh, Standard_True);
1428       }
1429     }
1430   }
1431   return 0;
1432 }
1433
1434 //-----------------------------------------------------------------------------
1435
1436 static Standard_Integer mdisplay
1437 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1438 {
1439   if (argc<2)
1440     di << "Wrong number of parameters\n";
1441   else
1442   {
1443     Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1444     if( !aMesh.IsNull() )
1445     {
1446       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1447
1448       if( aContext.IsNull() )
1449         di << "The context is null\n";
1450       else
1451       {
1452         aContext->Display (aMesh, Standard_True);
1453       }
1454     }
1455   }
1456   return 0;
1457 }
1458 //-----------------------------------------------------------------------------
1459 static Standard_Integer merase
1460 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1461 {
1462   if (argc<2)
1463     di << "Wrong number of parameters\n";
1464   else
1465   {
1466     Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1467     if( !aMesh.IsNull() )
1468     {
1469       Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1470
1471       if( aContext.IsNull() )
1472         di << "The context is null\n";
1473       else
1474       {
1475         aContext->Erase (aMesh, Standard_True);
1476       }
1477     }
1478     else
1479       di << "Mesh is null\n";
1480   }
1481   return 0;
1482 }
1483 //-----------------------------------------------------------------------------
1484 static Standard_Integer hidesel
1485 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1486 {
1487   if (argc<2)
1488   {
1489     di << "Wrong number of parameters\n";
1490     di << "Use: " << argv[0] << " <mesh name>\n";
1491     return 0;
1492   }
1493
1494   Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1495   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1496   if( aMesh.IsNull() )
1497   {
1498     di << "The mesh is invalid\n";
1499     return 0;
1500   }
1501
1502   if( aContext.IsNull() )
1503     di << "The context is null\n";
1504   else
1505   {
1506     Handle(TColStd_HPackedMapOfInteger) aHiddenNodes = aMesh->GetHiddenNodes();
1507     if (aHiddenNodes.IsNull())
1508     {
1509       aHiddenNodes = new TColStd_HPackedMapOfInteger();
1510     }
1511     Handle(TColStd_HPackedMapOfInteger) aHiddenElements = aMesh->GetHiddenElems();
1512     if (aHiddenElements.IsNull())
1513     {
1514       aHiddenElements = new TColStd_HPackedMapOfInteger();
1515     }
1516     for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
1517     {
1518       Handle( MeshVS_MeshEntityOwner ) anOwner =
1519         Handle( MeshVS_MeshEntityOwner )::DownCast( aContext->SelectedOwner() );
1520       if( !anOwner.IsNull() )
1521       {
1522         if( anOwner->Type()==MeshVS_ET_Node )
1523         {
1524           aHiddenNodes->ChangeMap().Add( anOwner->ID() );
1525         }
1526         else
1527         {
1528           aHiddenElements->ChangeMap().Add( anOwner->ID() );
1529         }
1530       }
1531     }
1532     aContext->ClearSelected (Standard_False);
1533     aMesh->SetHiddenNodes( aHiddenNodes );
1534     aMesh->SetHiddenElems( aHiddenElements );
1535     aContext->Redisplay (aMesh, Standard_True);
1536   }
1537
1538   return 0;
1539 }
1540 //-----------------------------------------------------------------------------
1541 static Standard_Integer showonly
1542 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1543 {
1544   if (argc<2)
1545   {
1546     di << "Wrong number of parameters\n";
1547     di << "Use: " << argv[0] << " <mesh name>\n";
1548     return 0;
1549   }
1550
1551
1552   Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1553   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1554   if( aMesh.IsNull() )
1555   {
1556     di << "The mesh is invalid\n";
1557     return 0;
1558   }
1559
1560   if( aContext.IsNull() )
1561     di << "The context is null\n";
1562   else
1563   {
1564     Handle(TColStd_HPackedMapOfInteger) aHiddenNodes =
1565       new TColStd_HPackedMapOfInteger(aMesh->GetDataSource()->GetAllNodes());
1566     Handle(TColStd_HPackedMapOfInteger) aHiddenElements =
1567       new TColStd_HPackedMapOfInteger(aMesh->GetDataSource()->GetAllElements());
1568     for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
1569     {
1570       Handle( MeshVS_MeshEntityOwner ) anOwner =
1571         Handle( MeshVS_MeshEntityOwner )::DownCast( aContext->SelectedOwner() );
1572       if( !anOwner.IsNull() )
1573       {
1574         if( anOwner->Type() == MeshVS_ET_Node )
1575         {
1576           aHiddenNodes->ChangeMap().Remove( anOwner->ID() );
1577         }
1578         else
1579         {
1580           aHiddenElements->ChangeMap().Remove( anOwner->ID() );
1581         }
1582       }
1583     }
1584     aMesh->SetHiddenNodes( aHiddenNodes );
1585     aMesh->SetHiddenElems( aHiddenElements );
1586     aContext->Redisplay (aMesh, Standard_True);
1587   }
1588
1589   return 0;
1590 }
1591 //-----------------------------------------------------------------------------
1592 static Standard_Integer showall
1593 (Draw_Interpretor& di, Standard_Integer argc, const char** argv )
1594 {
1595   if (argc<2)
1596   {
1597     di << "Wrong number of parameters\n";
1598     di << "Use: " << argv[0] << " <mesh name>\n";
1599     return 0;
1600   }
1601
1602   Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1603   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[1], di );
1604   if( aMesh.IsNull() )
1605   {
1606     di << "The mesh is invalid\n";
1607     return 0;
1608   }
1609
1610   if( aContext.IsNull() )
1611     di << "The context is null\n";
1612   else
1613   {
1614     aMesh->SetHiddenNodes( new TColStd_HPackedMapOfInteger() );
1615     aMesh->SetHiddenElems( new TColStd_HPackedMapOfInteger() );
1616     aContext->Redisplay (aMesh, Standard_True);
1617   }
1618
1619   return 0;
1620 }
1621
1622 //-----------------------------------------------------------------------------
1623 static Standard_Integer meshcolors( Draw_Interpretor& di,
1624                                     Standard_Integer argc,
1625                                     const char** argv )
1626 {
1627   try
1628   {
1629     OCC_CATCH_SIGNALS
1630       if ( argc < 4 )
1631       {
1632         di << "Wrong number of parameters\n";
1633         di << "Use : meshcolors <mesh name> <mode> <isreflect>\n";
1634         di << "mode : {elem1|elem2|nodal|nodaltex|none}\n";
1635         di << "       elem1 - different color for each element\n";
1636         di << "       elem2 - one color for one side\n";
1637         di << "       nodal - different color for each node\n";
1638         di << "       nodaltex - different color for each node with texture interpolation\n";
1639         di << "       none  - clear\n";
1640         di << "isreflect : {0|1} \n";
1641
1642         return 0;
1643       }
1644
1645       Handle( MeshVS_Mesh ) aMesh = getMesh( argv[ 1 ], di );
1646
1647       if ( aMesh.IsNull() )
1648       {
1649         di << "Mesh not found\n";
1650         return 0;
1651       }
1652       Handle(AIS_InteractiveContext) anIC = ViewerTest::GetAISContext();
1653       if ( anIC.IsNull() )
1654       {
1655         di << "The context is null\n";
1656         return 0;
1657       }
1658       if( !aMesh.IsNull() )
1659       {
1660         TCollection_AsciiString aMode = TCollection_AsciiString (argv[2]);
1661         Quantity_Color aColor1(Quantity_NOC_BLUE1);
1662         Quantity_Color aColor2(Quantity_NOC_RED1);
1663         if( aMode.IsEqual("elem1") || aMode.IsEqual("elem2") || aMode.IsEqual("nodal") || aMode.IsEqual("nodaltex") || aMode.IsEqual("none") )
1664         {
1665           Handle(MeshVS_PrsBuilder) aTempBuilder;
1666           Standard_Integer aReflection = Draw::Atoi(argv[3]);
1667
1668           for (Standard_Integer aCount = 0 ; aCount < aMesh->GetBuildersCount(); aCount++ ){
1669             aTempBuilder = aMesh->FindBuilder("MeshVS_ElementalColorPrsBuilder");
1670             if( !aTempBuilder.IsNull())
1671               aMesh->RemoveBuilderById(aTempBuilder->GetId());
1672
1673             aTempBuilder = aMesh->FindBuilder("MeshVS_NodalColorPrsBuilder");
1674             if( !aTempBuilder.IsNull())
1675               aMesh->RemoveBuilderById(aTempBuilder->GetId());
1676           }
1677
1678           if( aMode.IsEqual("elem1") || aMode.IsEqual("elem2") )
1679           {
1680             Handle(MeshVS_ElementalColorPrsBuilder) aBuilder = new MeshVS_ElementalColorPrsBuilder(
1681                 aMesh, MeshVS_DMF_ElementalColorDataPrs | MeshVS_DMF_OCCMask );
1682               // Color
1683             const TColStd_PackedMapOfInteger& anAllElements = aMesh->GetDataSource()->GetAllElements();
1684             TColStd_MapIteratorOfPackedMapOfInteger anIter( anAllElements );
1685
1686             if( aMode.IsEqual("elem1") )
1687               for ( ; anIter.More(); anIter.Next() )
1688               {
1689                 Quantity_Color aColor( (Quantity_NameOfColor)( anIter.Key() % Quantity_NOC_WHITE ) );
1690                 aBuilder->SetColor1( anIter.Key(), aColor );
1691               }
1692             else
1693               for ( ; anIter.More(); anIter.Next() )
1694                 aBuilder->SetColor2( anIter.Key(), aColor1, aColor2 );
1695
1696             aMesh->AddBuilder( aBuilder, Standard_True );
1697           }
1698
1699
1700           if( aMode.IsEqual("nodal") )
1701           {
1702             Handle(MeshVS_NodalColorPrsBuilder) aBuilder = new MeshVS_NodalColorPrsBuilder(
1703                 aMesh, MeshVS_DMF_NodalColorDataPrs | MeshVS_DMF_OCCMask );
1704             aMesh->AddBuilder( aBuilder, Standard_True );
1705
1706             // Color
1707             const TColStd_PackedMapOfInteger& anAllNodes =
1708               aMesh->GetDataSource()->GetAllNodes();
1709             TColStd_MapIteratorOfPackedMapOfInteger anIter( anAllNodes );
1710             for ( ; anIter.More(); anIter.Next() )
1711             {
1712               Quantity_Color aColor( (Quantity_NameOfColor)(
1713                 anIter.Key() % Quantity_NOC_WHITE ) );
1714               aBuilder->SetColor( anIter.Key(), aColor );
1715             }
1716             aMesh->AddBuilder( aBuilder, Standard_True );
1717           }
1718
1719           if(aMode.IsEqual("nodaltex"))
1720           {
1721             // assign nodal builder to the mesh
1722             Handle(MeshVS_NodalColorPrsBuilder) aBuilder = new MeshVS_NodalColorPrsBuilder(
1723                    aMesh, MeshVS_DMF_NodalColorDataPrs | MeshVS_DMF_OCCMask);
1724             aMesh->AddBuilder(aBuilder, Standard_True);
1725             aBuilder->UseTexture(Standard_True);
1726
1727             // prepare color map for texture
1728             Aspect_SequenceOfColor aColorMap;
1729             aColorMap.Append((Quantity_NameOfColor) Quantity_NOC_RED);
1730             aColorMap.Append((Quantity_NameOfColor) Quantity_NOC_YELLOW);
1731             aColorMap.Append((Quantity_NameOfColor) Quantity_NOC_BLUE1);
1732
1733             // prepare scale map for mesh - it will be assigned to mesh as texture coordinates
1734             // make mesh color interpolated from minimum X coord to maximum X coord
1735             Handle(MeshVS_DataSource) aDataSource = aMesh->GetDataSource();
1736             Standard_Real aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ;
1737
1738             // get bounding box for calculations
1739             aDataSource->GetBoundingBox().Get(aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ);
1740             Standard_Real aDelta = aMaxX - aMinX;
1741
1742             // assign color scale map values (0..1) to nodes
1743             TColStd_DataMapOfIntegerReal aScaleMap;
1744             TColStd_Array1OfReal aCoords(1, 3);
1745             Standard_Integer     aNbNodes;
1746             MeshVS_EntityType    aType;
1747
1748             // iterate nodes
1749             const TColStd_PackedMapOfInteger& anAllNodes =
1750                   aMesh->GetDataSource()->GetAllNodes();
1751             TColStd_MapIteratorOfPackedMapOfInteger anIter(anAllNodes);
1752             for (; anIter.More(); anIter.Next())
1753             {
1754               //get node coordinates to aCoord variable
1755               aDataSource->GetGeom(anIter.Key(), Standard_False, aCoords, aNbNodes, aType);
1756
1757               Standard_Real aScaleValue;
1758               try {
1759                 OCC_CATCH_SIGNALS
1760                 aScaleValue = (aCoords.Value(1) - (Standard_Real) aMinX) / aDelta;
1761               } catch(Standard_Failure const&) {
1762                 aScaleValue = 0;
1763               }
1764
1765               aScaleMap.Bind(anIter.Key(), aScaleValue);
1766             }
1767
1768             //set color map for builder and a color for invalid scale value
1769             aBuilder->SetColorMap(aColorMap);
1770             aBuilder->SetInvalidColor(Quantity_NOC_BLACK);
1771             aBuilder->SetTextureCoords(aScaleMap);
1772             aMesh->AddBuilder(aBuilder, Standard_True);
1773           }
1774
1775           aMesh->GetDrawer()->SetBoolean (MeshVS_DA_ColorReflection, aReflection != 0);
1776
1777           anIC->Redisplay (aMesh, Standard_True);
1778         }
1779         else
1780         {
1781           di << "Wrong mode name\n";
1782           return 0;
1783         }
1784       }
1785   }
1786   catch ( Standard_Failure const& )
1787   {
1788     di << "Error\n";
1789   }
1790
1791   return 0;
1792 }
1793 //-----------------------------------------------------------------------------
1794 static Standard_Integer meshvectors( Draw_Interpretor& di,
1795                                      Standard_Integer argc,
1796                                      const char** argv )
1797 {
1798   if ( argc < 3 )
1799   {
1800     di << "Wrong number of parameters\n";
1801     di << "Use : meshvectors <mesh name> < -mode {elem|nodal|none} > [-maxlen len] [-color name] [-arrowpart ratio] [-issimple {1|0}]\n";
1802     di << "Supported mode values:\n";
1803     di << "       elem  - vector per element\n";
1804     di << "       nodal - vector per node\n";
1805     di << "       none  - clear\n";
1806
1807     return 0;
1808   }
1809
1810   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[ 1 ], di );
1811
1812   if ( aMesh.IsNull() )
1813   {
1814     di << "Mesh not found\n";
1815     return 0;
1816   }
1817   Handle(AIS_InteractiveContext) anIC = ViewerTest::GetAISContext();
1818   if ( anIC.IsNull() )
1819   {
1820     di << "The context is null\n";
1821     return 0;
1822   }
1823
1824   TCollection_AsciiString aParam;
1825   TCollection_AsciiString aMode("none");
1826   Standard_Real           aMaxlen(1.0);
1827   Quantity_Color          aColor(Quantity_NOC_ORANGE);
1828   Standard_Real           anArrowPart(0.1);
1829   Standard_Boolean        isSimplePrs(Standard_False);
1830
1831   for (Standard_Integer anIdx = 2; anIdx < argc; anIdx++)
1832   {
1833     if (!aParam.IsEmpty())
1834     {
1835       if (aParam == "-mode")
1836       {
1837         aMode       = argv[anIdx];
1838       }
1839       else if (aParam == "-maxlen")
1840       {
1841         aMaxlen     = Draw::Atof(argv[anIdx]);
1842       }
1843       else if (aParam == "-color")
1844       {
1845         if (!Quantity_Color::ColorFromName (argv[anIdx], aColor))
1846         {
1847           Message::SendFail() << "Syntax error at " << aParam;
1848           return 1;
1849         }
1850       }
1851       else if (aParam == "-arrowpart")
1852       {
1853         anArrowPart = Draw::Atof(argv[anIdx]);
1854       }
1855       else if (aParam == "-issimple")
1856       {
1857         isSimplePrs = Draw::Atoi(argv[anIdx]) != 0;
1858       }
1859       aParam.Clear();
1860     }
1861     else if (argv[anIdx][0] == '-')
1862     {
1863       aParam = argv[anIdx];
1864     }
1865   }
1866
1867   if( !aMode.IsEqual("elem") && !aMode.IsEqual("nodal") && !aMode.IsEqual("none") )
1868   {
1869     di << "Wrong mode name\n";
1870     return 0;
1871   }
1872
1873   Handle(MeshVS_PrsBuilder) aTempBuilder;
1874
1875   aTempBuilder = aMesh->FindBuilder("MeshVS_VectorPrsBuilder");
1876   if( !aTempBuilder.IsNull())
1877     aMesh->RemoveBuilderById(aTempBuilder->GetId());
1878
1879   if( !aMode.IsEqual("none") )
1880   {
1881     Handle(MeshVS_VectorPrsBuilder) aBuilder = new MeshVS_VectorPrsBuilder( aMesh.operator->(), 
1882                                                                             aMaxlen,
1883                                                                             aColor,
1884                                                                             MeshVS_DMF_VectorDataPrs,
1885                                                                             0,
1886                                                                             -1,
1887                                                                             MeshVS_BP_Vector,
1888                                                                             isSimplePrs);
1889
1890     Standard_Boolean anIsElement = aMode.IsEqual("elem");
1891     const TColStd_PackedMapOfInteger& anAllIDs = anIsElement ? aMesh->GetDataSource()->GetAllElements() :
1892                                                                aMesh->GetDataSource()->GetAllNodes();
1893
1894     Standard_Integer aNbNodes;
1895     MeshVS_EntityType aEntType;
1896
1897     TColStd_Array1OfReal aCoords(1, 3);
1898     aCoords.Init (0.);
1899     TColStd_MapIteratorOfPackedMapOfInteger anIter( anAllIDs );
1900     for ( ; anIter.More(); anIter.Next() )
1901     {
1902       Standard_Boolean IsValidData = Standard_False; 
1903       if (anIsElement) {
1904         aMesh->GetDataSource()->GetGeomType(anIter.Key(), anIsElement, aEntType);
1905         if (aEntType == MeshVS_ET_Face)
1906           IsValidData = aMesh->GetDataSource()->GetNormal(anIter.Key(), 3, aCoords.ChangeValue(1), aCoords.ChangeValue(2), aCoords.ChangeValue(3));
1907       } else
1908         IsValidData = aMesh->GetDataSource()->GetGeom(anIter.Key(), Standard_False, aCoords, aNbNodes, aEntType);
1909
1910       gp_Vec aNorm;
1911       if(IsValidData)
1912       { 
1913         aNorm = gp_Vec(aCoords.Value(1), aCoords.Value(2), aCoords.Value(3));
1914         if(aNorm.Magnitude() < gp::Resolution())
1915         {
1916           aNorm = gp_Vec(0,0,1); //method GetGeom(...) returns coordinates of nodes
1917         }
1918       }
1919       else
1920       {
1921         aNorm = gp_Vec(0,0,1);
1922       }
1923       aBuilder->SetVector(anIsElement, anIter.Key(), aNorm.Normalized());
1924     }
1925
1926     aMesh->AddBuilder( aBuilder, Standard_False );
1927     aMesh->GetDrawer()->SetDouble ( MeshVS_DA_VectorArrowPart, anArrowPart );
1928   }
1929
1930   anIC->Redisplay (aMesh, Standard_True);
1931
1932   return 0;
1933 }
1934 //-----------------------------------------------------------------------------
1935
1936 static Standard_Integer meshtext( Draw_Interpretor& di,
1937                                   Standard_Integer argc,
1938                                   const char** argv )
1939 {
1940   if ( argc < 2 )
1941   {
1942     di << "Wrong number of parameters\n";
1943     di << "Use : meshtext <mesh name>\n";
1944     return 0;
1945   }
1946
1947   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[ 1 ], di );
1948
1949   if ( aMesh.IsNull() )
1950   {
1951     di << "Mesh not found\n";
1952     return 0;
1953   }
1954
1955   Handle(AIS_InteractiveContext) anIC = ViewerTest::GetAISContext();
1956   if ( anIC.IsNull() )
1957   {
1958     di << "The context is null\n";
1959     return 0;
1960   }
1961
1962   // Prepare triangle labels
1963   MeshVS_DataMapOfIntegerAsciiString aLabels;
1964   Standard_Integer aLen = aMesh->GetDataSource()->GetAllElements().Extent();
1965   for ( Standard_Integer anIndex = 1; anIndex <= aLen; anIndex++ ){
1966     aLabels.Bind( anIndex, TCollection_AsciiString( anIndex ) );
1967   }
1968
1969   Handle(MeshVS_TextPrsBuilder) aTextBuilder = new MeshVS_TextPrsBuilder( aMesh.operator->(), 20., Quantity_NOC_YELLOW );
1970   aTextBuilder->SetTexts( Standard_True, aLabels );
1971   aMesh->AddBuilder( aTextBuilder );
1972
1973   return 0;
1974 }
1975
1976 static Standard_Integer meshdeform( Draw_Interpretor& di,
1977                                     Standard_Integer argc,
1978                                     const char** argv )
1979 {
1980   if ( argc < 3 )
1981   {
1982     di << "Wrong number of parameters\n";
1983     di << "Use : meshdeform <mesh name> < -mode {on|off} > [-scale scalefactor]\n";
1984     return 0;
1985   }
1986
1987   Handle( MeshVS_Mesh ) aMesh = getMesh( argv[ 1 ], di );
1988
1989   if ( aMesh.IsNull() )
1990   {
1991     di << "Mesh not found\n";
1992     return 0;
1993   }
1994   Handle(AIS_InteractiveContext) anIC = ViewerTest::GetAISContext();
1995   if ( anIC.IsNull() )
1996   {
1997     di << "The context is null\n";
1998     return 0;
1999   }
2000
2001   TCollection_AsciiString aParam;
2002   TCollection_AsciiString aMode("off");
2003   Standard_Real           aScale(1.0);
2004
2005   for (Standard_Integer anIdx = 2; anIdx < argc; anIdx++)
2006   {
2007     if (!aParam.IsEmpty())
2008     {
2009       if (aParam == "-mode")
2010       {
2011         aMode = argv[anIdx];
2012       }
2013       else if (aParam == "-scale")
2014       {
2015         aScale = Draw::Atof(argv[anIdx]);
2016       }
2017       aParam.Clear();
2018     }
2019     else if (argv[anIdx][0] == '-')
2020     {
2021       aParam = argv[anIdx];
2022     }
2023   }
2024
2025   if(!aMode.IsEqual("on") && !aMode.IsEqual("off"))
2026   {
2027     di << "Wrong mode name\n";
2028     return 0;
2029   }
2030
2031   Handle ( MeshVS_DeformedDataSource ) aDefDS =
2032     new MeshVS_DeformedDataSource( aMesh->GetDataSource() , aScale );
2033
2034   const TColStd_PackedMapOfInteger& anAllIDs = aMesh->GetDataSource()->GetAllNodes();
2035
2036   Standard_Integer aNbNodes;
2037   MeshVS_EntityType aEntType;
2038
2039   TColStd_MapIteratorOfPackedMapOfInteger anIter( anAllIDs );
2040   for ( ; anIter.More(); anIter.Next() )
2041   {
2042     TColStd_Array1OfReal aCoords(1, 3);
2043     aMesh->GetDataSource()->GetGeom(anIter.Key(), Standard_False, aCoords, aNbNodes, aEntType);
2044
2045     gp_Vec aNorm = gp_Vec(aCoords.Value(1), aCoords.Value(2), aCoords.Value(3));
2046     if( !aNorm.Magnitude() )
2047       aNorm = gp_Vec(0,0,1);
2048     aDefDS->SetVector(anIter.Key(), aNorm.Normalized());
2049   }
2050
2051   aMesh->SetDataSource(aDefDS);
2052
2053   anIC->Redisplay (aMesh, Standard_False);
2054
2055   Handle( V3d_View ) aView = ViewerTest::CurrentView();
2056   if ( !aView.IsNull() )
2057     aView->FitAll();
2058
2059   return 0;
2060 }
2061
2062 static Standard_Integer mesh_edge_width( Draw_Interpretor& di,
2063                                         Standard_Integer argc,
2064                                         const char** argv )
2065 {
2066   try
2067   {
2068     OCC_CATCH_SIGNALS
2069       if ( argc < 3 )
2070       {
2071         di << "Wrong number of parameters\n";
2072         di << "Use : mesh_edge_width <mesh name> <width>\n";
2073         return 0;
2074       }
2075
2076       Handle(MeshVS_Mesh) aMesh = getMesh( argv[ 1 ], di );
2077       if ( aMesh.IsNull() )
2078       {
2079         di << "Mesh not found\n";
2080         return 0;
2081       }
2082
2083       const char* aWidthStr = argv[ 2 ];
2084       if ( aWidthStr == 0 || Draw::Atof( aWidthStr ) <= 0 )
2085       {
2086         di << "Width must be real value more than zero\n";
2087         return 0;
2088       }
2089
2090       double aWidth = Draw::Atof( aWidthStr );
2091
2092       Handle(AIS_InteractiveContext) anIC = ViewerTest::GetAISContext();
2093       if ( anIC.IsNull() )
2094       {
2095         di << "The context is null\n";
2096         return 0;
2097       }
2098
2099       Handle(MeshVS_Drawer) aDrawer = aMesh->GetDrawer();
2100       if ( aDrawer.IsNull() )
2101       {
2102         di << "The drawer is null\n";
2103         return 0;
2104       }
2105
2106       aDrawer->SetDouble( MeshVS_DA_EdgeWidth, aWidth );
2107       anIC->Redisplay (aMesh, Standard_True);
2108   }
2109   catch ( Standard_Failure const& )
2110   {
2111     di << "Error\n";
2112   }
2113
2114   return 0;
2115 }
2116
2117 //-----------------------------------------------------------------------------
2118
2119 static Standard_Integer meshinfo(Draw_Interpretor& di,
2120                                  Standard_Integer argc,
2121                                  const char** argv)
2122 {
2123   if ( argc != 2 )
2124   {
2125     di << "Wrong number of parameters. Use : meshinfo mesh\n";
2126     return 0;
2127   }
2128
2129   Handle(MeshVS_Mesh) aMesh = getMesh(argv[ 1 ], di);
2130   if ( aMesh.IsNull() )
2131   {
2132     di << "Mesh not found\n";
2133     return 0;
2134   }
2135
2136   Handle(XSDRAWSTLVRML_DataSource) stlMeshSource = Handle(XSDRAWSTLVRML_DataSource)::DownCast(aMesh->GetDataSource());
2137   if (!stlMeshSource.IsNull())
2138   {
2139     const TColStd_PackedMapOfInteger& nodes = stlMeshSource->GetAllNodes();
2140     const TColStd_PackedMapOfInteger& tris  = stlMeshSource->GetAllElements();
2141
2142     di << "Nb nodes = " << nodes.Extent() << "\n";
2143     di << "Nb triangles = " << tris.Extent() << "\n";
2144   }
2145
2146   return 0;
2147 }
2148
2149 //=======================================================================
2150 //function : writeply
2151 //purpose  : write PLY file
2152 //=======================================================================
2153 static Standard_Integer WritePly (Draw_Interpretor& theDI,
2154                                   Standard_Integer theNbArgs,
2155                                   const char** theArgVec)
2156 {
2157   Handle(TDocStd_Document) aDoc;
2158   Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
2159   TCollection_AsciiString aShapeName, aFileName;
2160
2161   Standard_Real aDist = 0.0;
2162   Standard_Real aDens = Precision::Infinite();
2163   Standard_Real aTol  = Precision::Confusion();
2164   bool hasColors = true, hasNormals = true, hasTexCoords = false, hasPartId = true, hasFaceId = false;
2165   bool isPntSet = false, isDensityPoints = false;
2166   TColStd_IndexedDataMapOfStringString aFileInfo;
2167   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
2168   {
2169     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2170     anArg.LowerCase();
2171     if (anArg == "-normal")
2172     {
2173       hasNormals = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
2174     }
2175     else if (anArg == "-nonormal")
2176     {
2177       hasNormals = !Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
2178     }
2179     else if (anArg == "-color"
2180           || anArg == "-nocolor"
2181           || anArg == "-colors"
2182           || anArg == "-nocolors")
2183     {
2184       hasColors = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
2185     }
2186     else if (anArg == "-uv"
2187           || anArg == "-nouv")
2188     {
2189       hasTexCoords = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
2190     }
2191     else if (anArg == "-partid")
2192     {
2193       hasPartId = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
2194       hasFaceId = hasFaceId && !hasPartId;
2195     }
2196     else if (anArg == "-surfid"
2197           || anArg == "-surfaceid"
2198           || anArg == "-faceid")
2199     {
2200       hasFaceId = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
2201       hasPartId = hasPartId && !hasFaceId;
2202     }
2203     else if (anArg == "-pntset"
2204           || anArg == "-pntcloud"
2205           || anArg == "-pointset"
2206           || anArg == "-pointcloud"
2207           || anArg == "-cloud"
2208           || anArg == "-points")
2209     {
2210       isPntSet = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
2211     }
2212     else if ((anArg == "-dist"
2213            || anArg == "-distance")
2214           && anArgIter + 1 < theNbArgs
2215           && Draw::ParseReal (theArgVec[anArgIter + 1], aDist))
2216     {
2217       ++anArgIter;
2218       isPntSet = true;
2219       if (aDist < 0.0)
2220       {
2221         theDI << "Syntax error: -distance value should be >= 0.0";
2222         return 1;
2223       }
2224       aDist = Max (aDist, Precision::Confusion());
2225     }
2226     else if ((anArg == "-dens"
2227            || anArg == "-density")
2228           && anArgIter + 1 < theNbArgs
2229           && Draw::ParseReal (theArgVec[anArgIter + 1], aDens))
2230     {
2231       ++anArgIter;
2232       isDensityPoints = Standard_True;
2233       isPntSet = true;
2234       if (aDens <= 0.0)
2235       {
2236         theDI << "Syntax error: -density value should be > 0.0";
2237         return 1;
2238       }
2239     }
2240     else if ((anArg == "-tol"
2241            || anArg == "-tolerance")
2242           && anArgIter + 1 < theNbArgs
2243           && Draw::ParseReal (theArgVec[anArgIter + 1], aTol))
2244     {
2245       ++anArgIter;
2246       isPntSet = true;
2247       if (aTol < Precision::Confusion())
2248       {
2249         theDI << "Syntax error: -tol value should be >= " << Precision::Confusion();
2250         return 1;
2251       }
2252     }
2253     else if (anArg == "-comments"
2254           && anArgIter + 1 < theNbArgs)
2255     {
2256       aFileInfo.Add ("Comments", theArgVec[++anArgIter]);
2257     }
2258     else if (anArg == "-author"
2259           && anArgIter + 1 < theNbArgs)
2260     {
2261       aFileInfo.Add ("Author", theArgVec[++anArgIter]);
2262     }
2263     else if (aDoc.IsNull())
2264     {
2265       if (aShapeName.IsEmpty())
2266       {
2267         aShapeName = theArgVec[anArgIter];
2268       }
2269
2270       Standard_CString aNameVar = theArgVec[anArgIter];
2271       DDocStd::GetDocument (aNameVar, aDoc, false);
2272       if (aDoc.IsNull())
2273       {
2274         TopoDS_Shape aShape = DBRep::Get (aNameVar);
2275         if (!aShape.IsNull())
2276         {
2277           anApp->NewDocument (TCollection_ExtendedString ("BinXCAF"), aDoc);
2278           Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (aDoc->Main());
2279           aShapeTool->AddShape (aShape);
2280         }
2281       }
2282     }
2283     else if (aFileName.IsEmpty())
2284     {
2285       aFileName = theArgVec[anArgIter];
2286     }
2287     else
2288     {
2289       theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
2290       return 1;
2291     }
2292   }
2293   if (aDoc.IsNull()
2294   && !aShapeName.IsEmpty())
2295   {
2296     theDI << "Syntax error: '" << aShapeName << "' is not a shape nor document";
2297     return 1;
2298   }
2299   else if (aDoc.IsNull()
2300         || aFileName.IsEmpty())
2301   {
2302     theDI << "Syntax error: wrong number of arguments";
2303     return 1;
2304   }
2305
2306   TDF_LabelSequence aRootLabels;
2307   Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (aDoc->Main());
2308   aShapeTool->GetFreeShapes (aRootLabels);
2309   if (aRootLabels.IsEmpty())
2310   {
2311     theDI << "Error: empty document";
2312     return 1;
2313   }
2314
2315   if (isPntSet)
2316   {
2317     class PointCloudPlyWriter : public BRepLib_PointCloudShape, public RWPly_PlyWriterContext
2318     {
2319     public:
2320       PointCloudPlyWriter (Standard_Real theTol)
2321       : BRepLib_PointCloudShape (TopoDS_Shape(), theTol) {}
2322
2323       void AddFaceColor (const TopoDS_Shape& theFace, const Graphic3d_Vec4ub& theColor)
2324       { myFaceColor.Bind (theFace, theColor); }
2325
2326     protected:
2327       virtual void addPoint (const gp_Pnt& thePoint,
2328                              const gp_Vec& theNorm,
2329                              const gp_Pnt2d& theUV,
2330                              const TopoDS_Shape& theFace)
2331       {
2332         Graphic3d_Vec4ub aColor;
2333         myFaceColor.Find (theFace, aColor);
2334         RWPly_PlyWriterContext::WriteVertex (thePoint,
2335                                              Graphic3d_Vec3 ((float )theNorm.X(), (float )theNorm.Y(), (float )theNorm.Z()),
2336                                              Graphic3d_Vec2 ((float )theUV.X(), (float )theUV.Y()),
2337                                              aColor);
2338       }
2339
2340     private:
2341       NCollection_DataMap<TopoDS_Shape, Graphic3d_Vec4ub> myFaceColor;
2342     };
2343
2344     PointCloudPlyWriter aPlyCtx (aTol);
2345     aPlyCtx.SetNormals (hasNormals);
2346     aPlyCtx.SetColors (hasColors);
2347     aPlyCtx.SetTexCoords (hasTexCoords);
2348
2349     TopoDS_Compound aComp;
2350     BRep_Builder().MakeCompound (aComp);
2351     for (XCAFPrs_DocumentExplorer aDocExplorer (aDoc, aRootLabels, XCAFPrs_DocumentExplorerFlags_OnlyLeafNodes);
2352          aDocExplorer.More(); aDocExplorer.Next())
2353     {
2354       const XCAFPrs_DocumentNode& aDocNode = aDocExplorer.Current();
2355       for (RWMesh_FaceIterator aFaceIter (aDocNode.RefLabel, aDocNode.Location, true, aDocNode.Style); aFaceIter.More(); aFaceIter.Next())
2356       {
2357         BRep_Builder().Add (aComp, aFaceIter.Face());
2358         Graphic3d_Vec4ub aColorVec (255);
2359         if (aFaceIter.HasFaceColor())
2360         {
2361           Graphic3d_Vec4 aColorF = aFaceIter.FaceColor();
2362           aColorVec.SetValues ((unsigned char )int(aColorF.r() * 255.0f),
2363                                (unsigned char )int(aColorF.g() * 255.0f),
2364                                (unsigned char )int(aColorF.b() * 255.0f),
2365                                (unsigned char )int(aColorF.a() * 255.0f));
2366         }
2367         aPlyCtx.AddFaceColor (aFaceIter.Face(), aColorVec);
2368       }
2369     }
2370     aPlyCtx.SetShape (aComp);
2371
2372     Standard_Integer aNbPoints = isDensityPoints
2373                                ? aPlyCtx.NbPointsByDensity (aDens)
2374                                : aPlyCtx.NbPointsByTriangulation();
2375     if (aNbPoints <= 0)
2376     {
2377       theDI << "Error: unable to generate points";
2378       return 0;
2379     }
2380
2381     if (!aPlyCtx.Open (aFileName)
2382      || !aPlyCtx.WriteHeader (aNbPoints, 0, TColStd_IndexedDataMapOfStringString()))
2383     {
2384       theDI << "Error: unable to create file '" << aFileName << "'";
2385       return 0;
2386     }
2387
2388     Standard_Boolean isDone = isDensityPoints
2389                             ? aPlyCtx.GeneratePointsByDensity (aDens)
2390                             : aPlyCtx.GeneratePointsByTriangulation();
2391     if (!isDone)
2392     {
2393       theDI << "Error: Point cloud was not generated in file '" << aFileName << "'";
2394     }
2395     else if (!aPlyCtx.Close())
2396     {
2397       theDI << "Error: Point cloud file '" << aFileName << "' was not written";
2398     }
2399     else
2400     {
2401       theDI << aNbPoints;
2402     }
2403   }
2404   else
2405   {
2406     Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
2407     RWPly_CafWriter aPlyCtx (aFileName);
2408     aPlyCtx.SetNormals (hasNormals);
2409     aPlyCtx.SetColors (hasColors);
2410     aPlyCtx.SetTexCoords (hasTexCoords);
2411     aPlyCtx.SetPartId (hasPartId);
2412     aPlyCtx.SetFaceId (hasFaceId);
2413     aPlyCtx.Perform (aDoc, aFileInfo, aProgress->Start());
2414   }
2415   return 0;
2416 }
2417
2418 //-----------------------------------------------------------------------------
2419
2420 void  XSDRAWSTLVRML::InitCommands (Draw_Interpretor& theCommands)
2421 {
2422   const char* g = "XSTEP-STL/VRML";  // Step transfer file commands
2423   //XSDRAW::LoadDraw(theCommands);
2424
2425   theCommands.Add ("ReadGltf",
2426                    "ReadGltf Doc file [-parallel {on|off}] [-listExternalFiles] [-noCreateDoc] [-doublePrecision {on|off}] [-assetInfo]"
2427                    "\n\t\t: Read glTF file into XDE document."
2428                    "\n\t\t:   -listExternalFiles do not read mesh and only list external files"
2429                    "\n\t\t:   -noCreateDoc read into existing XDE document"
2430                    "\n\t\t:   -doublePrecision store triangulation with double or single floating point"
2431                    "\n\t\t:                    precision (single by default)"
2432                    "\n\t\t:   -skipLateLoading data loading is skipped and can be performed later"
2433                    "\n\t\t:                    (false by default)"
2434                    "\n\t\t:   -keepLate data is loaded into itself with preservation of information"
2435                    "\n\t\t:             about deferred storage to load/unload this data later."
2436                    "\n\t\t:   -allScenes load all scenes defined in the document instead of default one (false by default)"
2437                    "\n\t\t:   -toPrintDebugInfo print additional debug information during data reading"
2438                    "\n\t\t:   -assetInfo print asset information",
2439                    __FILE__, ReadGltf, g);
2440   theCommands.Add ("readgltf",
2441                    "readgltf shape file"
2442                    "\n\t\t: Same as ReadGltf but reads glTF file into a shape instead of a document.",
2443                    __FILE__, ReadGltf, g);
2444   theCommands.Add ("WriteGltf",
2445                    "WriteGltf Doc file [-trsfFormat {compact|TRS|mat4}]=compact"
2446                    "\n\t\t:            [-systemCoordSys {Zup|Yup}]=Zup"
2447                    "\n\t\t:            [-comments Text] [-author Name]"
2448                    "\n\t\t:            [-forceUVExport]=0 [-texturesSeparate]=0 [-mergeFaces]=0 [-splitIndices16]=0"
2449                    "\n\t\t:            [-nodeNameFormat {empty|product|instance|instOrProd|prodOrInst|prodAndInst|verbose}]=instOrProd"
2450                    "\n\t\t:            [-meshNameFormat {empty|product|instance|instOrProd|prodOrInst|prodAndInst|verbose}]=product"
2451                    "\n\t\t:            [-draco]=0 [-compressionLevel {0-10}]=7 [-quantizePositionBits Value]=14 [-quantizeNormalBits Value]=10"
2452                    "\n\t\t:            [-quantizeTexcoordBits Value]=12 [-quantizeColorBits Value]=8 [-quantizeGenericBits Value]=12"
2453                    "\n\t\t:            [-unifiedQuantization]=0"
2454                    "\n\t\t: Write XDE document into glTF file."
2455                    "\n\t\t:   -trsfFormat       preferred transformation format"
2456                    "\n\t\t:   -systemCoordSys   system coordinate system; Zup when not specified"
2457                    "\n\t\t:   -mergeFaces       merge Faces within the same Mesh"
2458                    "\n\t\t:   -splitIndices16   split Faces to keep 16-bit indices when -mergeFaces is enabled"
2459                    "\n\t\t:   -forceUVExport    always export UV coordinates"
2460                    "\n\t\t:   -texturesSeparate write textures to separate files"
2461                    "\n\t\t:   -nodeNameFormat   name format for Nodes"
2462                    "\n\t\t:   -meshNameFormat   name format for Meshes"
2463                    "\n\t\t:   -draco use Draco  compression 3D geometric meshes"
2464                    "\n\t\t:   -compressionLevel draco compression level [0-10] (by default 7), a value of 0 will apply sequential encoding and preserve face order"
2465                    "\n\t\t:   -quantizePositionBits quantization bits for position attribute when using Draco compression (by default 14)"
2466                    "\n\t\t:   -quantizeNormalBits   quantization bits for normal attribute when using Draco compression (by default 10)"
2467                    "\n\t\t:   -quantizeTexcoordBits quantization bits for texture coordinate attribute when using Draco compression (by default 12)"
2468                    "\n\t\t:   -quantizeColorBits    quantization bits for color attribute when using Draco compression (by default 8)"
2469                    "\n\t\t:   -quantizeGenericBits  quantization bits for skinning attribute (joint indices and joint weights)"
2470                    "\n                        and custom attributes when using Draco compression (by default 12)"
2471                    "\n\t\t:   -unifiedQuantization  quantization is applied on each primitive separately if this option is false",
2472                    __FILE__, WriteGltf, g);
2473   theCommands.Add ("writegltf",
2474                    "writegltf shape file",
2475                    __FILE__, WriteGltf, g);
2476   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);
2477   theCommands.Add ("writestl",  "shape file [ascii/binary (0/1) : 1 by default] [InParallel (0/1) : 0 by default]",__FILE__,writestl,g);
2478   theCommands.Add ("readstl",
2479                    "readstl shape file [-brep] [-mergeAngle Angle] [-multi]"
2480                    "\n\t\t: Reads STL file and creates a new shape with specified name."
2481                    "\n\t\t: When -brep is specified, creates a Compound of per-triangle Faces."
2482                    "\n\t\t: Single triangulation-only Face is created otherwise (default)."
2483                    "\n\t\t: -mergeAngle specifies maximum angle in degrees between triangles to merge equal nodes; disabled by default."
2484                    "\n\t\t: -multi creates a face per solid in multi-domain files; ignored when -brep is set.",
2485                    __FILE__, readstl, g);
2486   theCommands.Add ("loadvrml" , "shape file",__FILE__,loadvrml,g);
2487   theCommands.Add ("ReadObj",
2488                    "ReadObj Doc file [-fileCoordSys {Zup|Yup}] [-fileUnit Unit]"
2489            "\n\t\t:                  [-resultCoordSys {Zup|Yup}] [-singlePrecision]"
2490            "\n\t\t:                  [-listExternalFiles] [-noCreateDoc]"
2491            "\n\t\t: Read OBJ file into XDE document."
2492            "\n\t\t:   -fileUnit       length unit of OBJ file content;"
2493            "\n\t\t:   -fileCoordSys   coordinate system defined by OBJ file; Yup when not specified."
2494            "\n\t\t:   -resultCoordSys result coordinate system; Zup when not specified."
2495            "\n\t\t:   -singlePrecision truncate vertex data to single precision during read; FALSE by default."
2496            "\n\t\t:   -listExternalFiles do not read mesh and only list external files."
2497            "\n\t\t:   -noCreateDoc    read into existing XDE document.",
2498                    __FILE__, ReadObj, g);
2499   theCommands.Add ("readobj",
2500                    "readobj shape file [-fileCoordSys {Zup|Yup}] [-fileUnit Unit]"
2501            "\n\t\t:                    [-resultCoordSys {Zup|Yup}] [-singlePrecision]"
2502            "\n\t\t:                    [-singleFace]"
2503            "\n\t\t: Same as ReadObj but reads OBJ file into a shape instead of a document."
2504            "\n\t\t:   -singleFace merge OBJ content into a single triangulation Face.",
2505            __FILE__, ReadObj, g);
2506   theCommands.Add ("WriteObj",
2507                    "WriteObj Doc file [-fileCoordSys {Zup|Yup}] [-fileUnit Unit]"
2508            "\n\t\t:                   [-systemCoordSys {Zup|Yup}]"
2509            "\n\t\t:                   [-comments Text] [-author Name]"
2510            "\n\t\t: Write XDE document into OBJ file."
2511            "\n\t\t:   -fileUnit       length unit of OBJ file content;"
2512            "\n\t\t:   -fileCoordSys   coordinate system defined by OBJ file; Yup when not specified."
2513            "\n\t\t:   -systemCoordSys system coordinate system; Zup when not specified.",
2514                    __FILE__, WriteObj, g);
2515   theCommands.Add ("writeobj",
2516                    "writeobj shape file",
2517                    __FILE__, WriteObj, g);
2518
2519   theCommands.Add ("meshfromstl",     "creates MeshVS_Mesh from STL file",            __FILE__, createmesh,      g );
2520   theCommands.Add ("mesh3delem",      "creates 3d element mesh to test",              __FILE__, create3d,        g );
2521   theCommands.Add ("meshshadcolor",   "change MeshVS_Mesh shading color",             __FILE__, meshcolor,       g );
2522   theCommands.Add ("meshlinkcolor",   "change MeshVS_Mesh line color",                __FILE__, linecolor,       g );
2523   theCommands.Add ("meshmat",         "change MeshVS_Mesh material and transparency", __FILE__, meshmat,         g );
2524   theCommands.Add ("meshshrcoef",     "change MeshVS_Mesh shrink coeff",              __FILE__, shrink,          g );
2525   theCommands.Add ("meshclosed",      "meshclosed meshname (0/1) \nChange MeshVS_Mesh drawing mode. 0 - not closed object, 1 - closed object", __FILE__, closed, g);
2526   theCommands.Add ("meshshow",        "display MeshVS_Mesh object",                   __FILE__, mdisplay,        g );
2527   theCommands.Add ("meshhide",        "erase MeshVS_Mesh object",                     __FILE__, merase,          g );
2528   theCommands.Add ("meshhidesel",     "hide selected entities",                       __FILE__, hidesel,         g );
2529   theCommands.Add ("meshshowsel",     "show only selected entities",                  __FILE__, showonly,        g );
2530   theCommands.Add ("meshshowall",     "show all entities",                            __FILE__, showall,         g );
2531   theCommands.Add ("meshcolors",      "display color presentation",                   __FILE__, meshcolors,      g );
2532   theCommands.Add ("meshvectors",     "display sample vectors",                       __FILE__, meshvectors,     g );
2533   theCommands.Add ("meshtext",        "display text labels",                          __FILE__, meshtext,        g );
2534   theCommands.Add ("meshdeform",      "display deformed mesh",                        __FILE__, meshdeform,      g );
2535   theCommands.Add ("mesh_edge_width", "set width of edges",                           __FILE__, mesh_edge_width, g );
2536   theCommands.Add ("meshinfo",        "displays the number of nodes and triangles",   __FILE__, meshinfo,        g );
2537   theCommands.Add ("WritePly", R"(
2538 WritePly Doc file [-normals {0|1}]=1 [-colors {0|1}]=1 [-uv {0|1}]=0 [-partId {0|1}]=1 [-faceId {0|1}]=0
2539                   [-pointCloud {0|1}]=0 [-distance Value]=0.0 [-density Value] [-tolerance Value]
2540 Write document or triangulated shape into PLY file.
2541  -normals write per-vertex normals
2542  -colors  write per-vertex colors
2543  -uv      write per-vertex UV coordinates
2544  -partId  write per-element part index (alternative to -faceId)
2545  -faceId  write per-element face index (alternative to -partId)
2546
2547 Generate point cloud out of the shape and write it into PLY file.
2548  -pointCloud write point cloud instead without triangulation indices
2549  -distance   sets distance from shape into the range [0, Value];
2550  -density    sets density of points to generate randomly on surface;
2551  -tolerance  sets tolerance; default value is Precision::Confusion();
2552 )", __FILE__, WritePly, g);
2553   theCommands.Add ("writeply",
2554                    "writeply shape file",
2555                    __FILE__, WritePly, g);
2556 }
2557
2558 //==============================================================================
2559 // XSDRAWSTLVRML::Factory
2560 //==============================================================================
2561 void XSDRAWSTLVRML::Factory(Draw_Interpretor& theDI)
2562 {
2563   XSDRAWIGES::InitSelect();
2564   XSDRAWIGES::InitToBRep(theDI);
2565   XSDRAWIGES::InitFromBRep(theDI);
2566   XSDRAWSTEP::InitCommands(theDI);
2567   XSDRAWSTLVRML::InitCommands(theDI);
2568   XSDRAW::LoadDraw(theDI);
2569 #ifdef OCCT_DEBUG
2570   theDI << "Draw Plugin : All TKXSDRAW commands are loaded\n";
2571 #endif
2572 }
2573
2574 // Declare entry point PLUGINFACTORY
2575 DPLUGIN(XSDRAWSTLVRML)
2576