0025279: OCCT fails to read VRML file created by OCCT
[occt.git] / src / VrmlAPI / VrmlAPI_Writer.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <Standard_Stream.hxx>
15 #include <VrmlAPI_Writer.ixx>
16 #include <Vrml_Material.hxx>
17 #include <Quantity_HArray1OfColor.hxx>
18 #include <TopoDS_Shape.hxx>
19 #include <TColStd_HArray1OfReal.hxx>
20 #include <OSD_Path.hxx>
21 #include <VrmlConverter_IsoAspect.hxx>
22 #include <VrmlConverter_LineAspect.hxx>
23 #include <VrmlConverter_PointAspect.hxx>
24 #include <VrmlConverter_ShadingAspect.hxx>
25 #include <TopTools_Array1OfShape.hxx>
26 #include <Vrml.hxx>
27 #include <VrmlConverter_Projector.hxx>
28 #include <VrmlConverter_ShadedShape.hxx>
29 #include <Vrml_Group.hxx>
30 #include <Vrml_Instancing.hxx>
31 #include <Vrml_Separator.hxx>
32 #include <VrmlConverter_WFDeflectionShape.hxx>
33 #include <VrmlData_Scene.hxx>
34 #include <VrmlData_ShapeConvert.hxx>
35 #include <OSD_OpenFile.hxx>
36 #include <TopExp_Explorer.hxx>
37 #include <TopAbs_ShapeEnum.hxx>
38 #include <TopoDS.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <Poly_Triangulation.hxx>
41 #include <BRep_Tool.hxx>
42
43 VrmlAPI_Writer::VrmlAPI_Writer()
44 {
45   myDrawer = new VrmlConverter_Drawer;
46   myDeflection = -1;
47   Quantity_Color color;
48   color.SetValues(0, 0, 0, Quantity_TOC_RGB);
49   Handle(Quantity_HArray1OfColor) Col1 = new Quantity_HArray1OfColor(1,1);
50   Col1->SetValue(1,color);
51   Handle(TColStd_HArray1OfReal) kik1 = new TColStd_HArray1OfReal(1,1,0.0);
52   Handle(TColStd_HArray1OfReal) kik2 = new TColStd_HArray1OfReal(1,1,0.1);
53   myFrontMaterial = new Vrml_Material(Col1,Col1, Col1, Col1, kik1, kik2);
54   myPointsMaterial = new Vrml_Material(Col1,Col1, Col1, Col1, kik1, kik2);
55   myUisoMaterial = new Vrml_Material(Col1,Col1, Col1, Col1, kik1, kik2);
56   myVisoMaterial = new Vrml_Material(Col1,Col1, Col1, Col1, kik1, kik2);
57   myLineMaterial = new Vrml_Material(Col1,Col1, Col1, Col1, kik1, kik2);
58   myWireMaterial = new Vrml_Material(Col1,Col1, Col1, Col1, kik1, kik2);
59   myFreeBoundsMaterial = new Vrml_Material(Col1,Col1, Col1, Col1, kik1, kik2);
60   myUnfreeBoundsMaterial = new Vrml_Material(Col1,Col1, Col1, Col1, kik1, kik2);
61   DX = 1;      
62   DY = -1;  
63   DZ = 1;
64   XUp = 0;
65   YUp = 0;
66   ZUp = 1;
67   Focus = 6;
68   ResetToDefaults();
69 }
70
71 void VrmlAPI_Writer::ResetToDefaults() 
72 {
73   myTransparency = 0.0;
74   myShininess = 0.1;
75   Handle(TColStd_HArray1OfReal) kik1 = new TColStd_HArray1OfReal(1,1,myTransparency);
76   Handle(TColStd_HArray1OfReal) kik2 = new TColStd_HArray1OfReal(1,1,myShininess);
77   Handle(Quantity_HArray1OfColor) Col = new Quantity_HArray1OfColor(1,1);
78   Quantity_Color color; 
79   color.SetValues(0, 0, 0, Quantity_TOC_RGB);
80   Col->SetValue(1,color);
81   //
82   myFrontMaterial->SetAmbientColor(Col); myFrontMaterial->SetTransparency(kik1);myFrontMaterial->SetShininess(kik2);
83   myPointsMaterial->SetAmbientColor(Col); myPointsMaterial->SetTransparency(kik1);myPointsMaterial->SetShininess(kik2);
84   myUisoMaterial->SetAmbientColor(Col); myUisoMaterial->SetTransparency(kik1);myUisoMaterial->SetShininess(kik2);
85   myVisoMaterial->SetAmbientColor(Col); myVisoMaterial->SetTransparency(kik1);myVisoMaterial->SetShininess(kik2);
86   myLineMaterial->SetAmbientColor(Col); myLineMaterial->SetTransparency(kik1);myLineMaterial->SetShininess(kik2);
87   myWireMaterial->SetAmbientColor(Col); myWireMaterial->SetTransparency(kik1); myWireMaterial->SetShininess(kik2);
88   myFreeBoundsMaterial->SetAmbientColor(Col); myFreeBoundsMaterial->SetTransparency(kik1);myFreeBoundsMaterial->SetShininess(kik2);
89   myUnfreeBoundsMaterial->SetAmbientColor(Col); myUnfreeBoundsMaterial->SetTransparency(kik1);myUnfreeBoundsMaterial->SetShininess(kik2);
90   //
91   //
92   Handle(Quantity_HArray1OfColor) Col2 = new Quantity_HArray1OfColor(1,1);
93   color.SetValues(0.75, 0.75, 0.75, Quantity_TOC_RGB);
94   Col2->SetValue(1,color);
95   Handle(Quantity_HArray1OfColor) Col3 = new Quantity_HArray1OfColor(1,1);
96   color.SetValues(0.82, 0.79, 0.42, Quantity_TOC_RGB);
97   Col3->SetValue(1,color);
98   
99   myUisoMaterial->SetDiffuseColor(Col2);
100   myVisoMaterial->SetDiffuseColor(Col2);
101   myFreeBoundsMaterial->SetDiffuseColor(Col2);
102   myUnfreeBoundsMaterial->SetDiffuseColor(Col2);
103   
104   //
105 //  Handle(Quantity_HArray1OfColor) Col3 = new Quantity_HArray1OfColor(1,1);
106 //  color.SetValues(Quantity_NOC_GOLD);
107 //  Col3->SetValue(1,color);
108   myLineMaterial->SetDiffuseColor(Col2);
109   myWireMaterial->SetDiffuseColor(Col2);
110   //
111 //  Handle(Quantity_HArray1OfColor) Col4 = new Quantity_HArray1OfColor(1,1);
112 //  color.SetValues(Quantity_NOC_GOLD);
113 //  Col4->SetValue(1,color);
114   myFrontMaterial->SetDiffuseColor(Col2);
115   myPointsMaterial->SetDiffuseColor(Col2);
116   //
117   
118   myUisoMaterial->SetSpecularColor(Col3);
119   myVisoMaterial->SetSpecularColor(Col3);
120   myFreeBoundsMaterial->SetSpecularColor(Col3);
121   myUnfreeBoundsMaterial->SetSpecularColor(Col3);
122   myLineMaterial->SetSpecularColor(Col3);
123   myWireMaterial->SetSpecularColor(Col3);
124   myFrontMaterial->SetSpecularColor(Col3);
125   myPointsMaterial->SetSpecularColor(Col3);
126   
127   myRepresentation = VrmlAPI_BothRepresentation;
128 }
129 Handle(VrmlConverter_Drawer) VrmlAPI_Writer::Drawer() const
130 {
131   return myDrawer;
132 }
133 void VrmlAPI_Writer::SetDeflection(const Standard_Real aDef)
134 {
135   myDeflection = aDef;
136   if (myDeflection > 0) {
137     myDrawer->SetMaximalChordialDeviation(myDeflection);
138     myDrawer->SetTypeOfDeflection(Aspect_TOD_ABSOLUTE);
139   }
140   else myDrawer->SetTypeOfDeflection(Aspect_TOD_RELATIVE);
141 }
142 void VrmlAPI_Writer::SetRepresentation(const VrmlAPI_RepresentationOfShape aRep)
143 {
144   myRepresentation = aRep;
145 }
146 void VrmlAPI_Writer::SetTransparencyToMaterial(Handle(Vrml_Material)& aMaterial,const Standard_Real aTransparency) 
147 {
148   Handle(TColStd_HArray1OfReal) t = new TColStd_HArray1OfReal(1,1,aTransparency);
149   aMaterial->SetTransparency(t);
150 }
151
152 void VrmlAPI_Writer::SetShininessToMaterial(Handle(Vrml_Material)& aMaterial,const Standard_Real aShininess) 
153 {  
154   Handle(TColStd_HArray1OfReal) s = new TColStd_HArray1OfReal(1,1,aShininess);
155   aMaterial->SetShininess(s);
156 }
157
158 void VrmlAPI_Writer::SetAmbientColorToMaterial(Handle(Vrml_Material)& aMaterial,const Handle(Quantity_HArray1OfColor)& Color) 
159 {
160   aMaterial->SetAmbientColor(Color);
161 }
162
163 void VrmlAPI_Writer::SetDiffuseColorToMaterial(Handle(Vrml_Material)& aMaterial,const Handle(Quantity_HArray1OfColor)& Color) 
164 {
165   aMaterial->SetDiffuseColor(Color);
166 }
167
168 void VrmlAPI_Writer::SetSpecularColorToMaterial(Handle(Vrml_Material)& aMaterial,const Handle(Quantity_HArray1OfColor)& Color) 
169 {
170   aMaterial->SetSpecularColor(Color);
171 }
172
173 void VrmlAPI_Writer::SetEmissiveColorToMaterial(Handle(Vrml_Material)& aMaterial,const Handle(Quantity_HArray1OfColor)& Color) 
174 {
175   aMaterial->SetEmissiveColor(Color);
176 }
177
178 VrmlAPI_RepresentationOfShape VrmlAPI_Writer::GetRepresentation() const
179 {
180   return myRepresentation;  
181 }
182
183 Handle(Vrml_Material) VrmlAPI_Writer::GetFrontMaterial() const
184 {
185   return myFrontMaterial;
186 }
187
188 Handle(Vrml_Material) VrmlAPI_Writer::GetPointsMaterial() const
189 {
190   return myPointsMaterial;
191 }
192
193 Handle(Vrml_Material) VrmlAPI_Writer::GetUisoMaterial() const
194 {
195   return myUisoMaterial;
196 }
197
198 Handle(Vrml_Material) VrmlAPI_Writer::GetVisoMaterial() const
199 {
200   return myVisoMaterial;
201 }
202
203 Handle(Vrml_Material) VrmlAPI_Writer::GetLineMaterial() const
204 {
205   return myLineMaterial;
206 }
207
208 Handle(Vrml_Material) VrmlAPI_Writer::GetWireMaterial() const
209 {
210   return myWireMaterial;
211 }
212
213 Handle(Vrml_Material) VrmlAPI_Writer::GetFreeBoundsMaterial() const
214 {
215   return myFreeBoundsMaterial;
216 }
217
218 Handle(Vrml_Material) VrmlAPI_Writer::GetUnfreeBoundsMaterial() const
219 {
220   return myUnfreeBoundsMaterial;
221 }
222
223 void VrmlAPI_Writer::Write(const TopoDS_Shape& aShape,const Standard_CString aFile, const Standard_Integer aVersion) const
224 {
225   if (aVersion == 1)
226     write_v1(aShape, aFile);
227   else if (aVersion == 2)
228     write_v2(aShape, aFile);
229 }
230
231 void VrmlAPI_Writer::write_v1(const TopoDS_Shape& aShape,const Standard_CString aFile) const
232 {
233   OSD_Path thePath(aFile);
234   TCollection_AsciiString theFile;thePath.SystemName(theFile);
235   ofstream outfile;
236   OSD_OpenStream(outfile, theFile.ToCString(), ios::out);
237   Handle(VrmlConverter_IsoAspect) ia = new VrmlConverter_IsoAspect;  // UIso
238   Handle(VrmlConverter_IsoAspect) ia1 = new VrmlConverter_IsoAspect; //VIso
239   ia->SetMaterial(myUisoMaterial);
240   ia->SetHasMaterial(Standard_True);
241   myDrawer->SetUIsoAspect(ia);
242   ia1->SetMaterial(myVisoMaterial);
243   ia1->SetHasMaterial(Standard_True);
244   myDrawer->SetVIsoAspect(ia1);
245 // default Number of iso lines is 10
246 //----  Definition of LineAspect (default - without own material)
247   Handle(VrmlConverter_LineAspect) la = new VrmlConverter_LineAspect;
248   la->SetMaterial(myLineMaterial);
249   la->SetHasMaterial(Standard_True);
250   myDrawer->SetLineAspect(la);
251 //----  Definition of Wire (without any neighbour)
252   Handle(VrmlConverter_LineAspect) lw = new VrmlConverter_LineAspect;
253   lw->SetMaterial(myWireMaterial);
254   lw->SetHasMaterial(Standard_True);
255   myDrawer->SetWireAspect(lw);
256 //----  Definition of Free boundaries
257   Handle(VrmlConverter_LineAspect) lf = new VrmlConverter_LineAspect;
258   lf->SetMaterial(myFreeBoundsMaterial);
259   lf->SetHasMaterial(Standard_True);
260   myDrawer->SetFreeBoundaryAspect(lf);
261 //----  Definition of Unfree boundaries
262   Handle(VrmlConverter_LineAspect) lun = new VrmlConverter_LineAspect;
263   lun->SetMaterial(myUnfreeBoundsMaterial);
264   lun->SetHasMaterial(Standard_True);
265   myDrawer->SetUnFreeBoundaryAspect(lun);
266 //----  Definition of Points (default - without own material)
267   Handle(VrmlConverter_PointAspect) pa = new VrmlConverter_PointAspect;
268   pa->SetMaterial(myPointsMaterial);
269   pa->SetHasMaterial(Standard_True);
270   myDrawer->SetPointAspect(pa);
271 //-----------------------------------------
272   Handle(VrmlConverter_ShadingAspect) sa = new VrmlConverter_ShadingAspect;
273   sa->SetFrontMaterial(myFrontMaterial);
274   sa->SetHasMaterial(Standard_True);
275   Vrml_ShapeHints  sh;
276   sa->SetShapeHints(sh);
277   myDrawer->SetShadingAspect(sa);
278 //-------- Shape --------------------------
279   TopTools_Array1OfShape Shapes(1,1);
280   Shapes.SetValue(1,aShape);
281
282   // Check shape tesselation
283   TopExp_Explorer anExp (aShape, TopAbs_FACE);
284   TopLoc_Location aLoc;
285   Standard_Boolean hasTriangles = Standard_False;
286   for (; anExp.More(); anExp.Next())
287   {
288     const TopoDS_Face& aFace = TopoDS::Face (anExp.Current());
289     if (!aFace.IsNull()) 
290     {
291       Handle(Poly_Triangulation) aTri =
292         BRep_Tool::Triangulation (aFace, aLoc);
293
294       if (!aTri.IsNull())
295       {
296         hasTriangles = Standard_True;
297         break;
298       }
299     }
300   }
301
302 //=========================================
303 //----  Definition of data for Projector
304 //=========================================
305
306   VrmlConverter_TypeOfLight Light = VrmlConverter_NoLight;
307   VrmlConverter_TypeOfCamera Camera = VrmlConverter_PerspectiveCamera;
308   Handle(VrmlConverter_Projector) projector = new VrmlConverter_Projector (Shapes, 
309                                                                            Focus, 
310                                                                            DX,  DY,  DZ, 
311                                                                            XUp, YUp, ZUp,
312                                                                            Camera,
313                                                                            Light);
314   Vrml::VrmlHeaderWriter(outfile);
315   if (myRepresentation == VrmlAPI_BothRepresentation)
316     Vrml::CommentWriter(" This file contents both Shaded and Wire Frame representation of selected Shape ",outfile);   
317   if (myRepresentation == VrmlAPI_ShadedRepresentation)
318     Vrml::CommentWriter(" This file contents only Shaded representation of selected Shape ",outfile);   
319   if (myRepresentation == VrmlAPI_WireFrameRepresentation)
320     Vrml::CommentWriter(" This file contents only Wire Frame representation of selected Shape ",outfile);   
321   Vrml_Separator S1;
322   S1.Print(outfile); 
323   projector->Add(outfile);
324   Light = VrmlConverter_DirectionLight;
325   Camera = VrmlConverter_OrthographicCamera;
326   Handle(VrmlConverter_Projector) projector1 = new VrmlConverter_Projector (Shapes, 
327                                                                            Focus, 
328                                                                            DX,  DY,  DZ, 
329                                                                            XUp, YUp, ZUp,
330                                                                            Camera,
331                                                                            Light);
332   projector1->Add(outfile);
333   Vrml_Separator S2;
334   S2.Print(outfile); 
335   if ( (myRepresentation == VrmlAPI_ShadedRepresentation || myRepresentation == VrmlAPI_BothRepresentation) && hasTriangles)
336     {
337       Vrml_Group Group1;
338       Group1.Print(outfile);
339       Vrml_Instancing I2 ("Shaded representation of shape");
340       I2.DEF(outfile);
341       VrmlConverter_ShadedShape::Add(outfile,aShape,myDrawer);
342       Group1.Print(outfile);
343     }
344   if (myRepresentation == VrmlAPI_WireFrameRepresentation || myRepresentation == VrmlAPI_BothRepresentation)
345     {
346       Vrml_Group Group2;
347       Group2.Print(outfile);
348       Vrml_Instancing I3 ("Wire Frame representation of shape");
349       I3.DEF(outfile);
350       VrmlConverter_WFDeflectionShape::Add(outfile,aShape,myDrawer);
351       Group2.Print(outfile);
352     }
353   S2.Print(outfile); 
354   S1.Print(outfile); 
355 }
356
357 void VrmlAPI_Writer::write_v2(const TopoDS_Shape& aShape,const Standard_CString aFile) const
358 {
359   Standard_Boolean anExtFace = Standard_False;
360   if(myRepresentation == VrmlAPI_ShadedRepresentation || myRepresentation == VrmlAPI_BothRepresentation) 
361     anExtFace = Standard_True;
362
363   Standard_Boolean anExtEdge = Standard_False;
364   if(myRepresentation == VrmlAPI_WireFrameRepresentation|| myRepresentation == VrmlAPI_BothRepresentation)
365     anExtEdge = Standard_True;
366
367   VrmlData_Scene aScene;
368   VrmlData_ShapeConvert aConv(aScene);
369   aConv.AddShape(aShape);
370   aConv.Convert(anExtFace, anExtEdge);
371
372   filebuf aFoc;
373   ostream outStream (&aFoc);
374   if (aFoc.open (aFile, ios::out))
375     outStream << aScene;
376 }