1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkX3DExporterXMLWriter.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen, Kristian Sons
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkX3DExporterXMLWriter.h"
16 
17 #include "vtkX3D.h"
18 #include "vtkObjectFactory.h"
19 #include "vtkDataArray.h"
20 #include "vtkUnsignedCharArray.h"
21 #include "vtkPoints.h"
22 #include "vtkCellArray.h"
23 #include "vtkMath.h"
24 
25 #include <sstream>
26 #include <fstream>
27 #include <string>
28 #include <cassert>
29 
30 using namespace vtkX3D;
31 
32 struct XMLInfo {
33 
XMLInfoXMLInfo34 XMLInfo(int _elementId)
35 {
36   this->elementId = _elementId;
37   this->endTagWritten = false;
38 }
39   int elementId;
40   bool endTagWritten;
41 };
42 
43 typedef std::vector<XMLInfo> vtkX3DExporterXMLNodeInfoStackBase;
44 class vtkX3DExporterXMLNodeInfoStack: public vtkX3DExporterXMLNodeInfoStackBase
45 {};
46 
47 //-----------------------------------------------------------------------------
48 vtkStandardNewMacro(vtkX3DExporterXMLWriter);
49 //-----------------------------------------------------------------------------
~vtkX3DExporterXMLWriter()50 vtkX3DExporterXMLWriter::~vtkX3DExporterXMLWriter()
51 {
52   delete this->InfoStack;
53   delete this->OutputStream;
54   this->OutputStream = nullptr;
55 }
56 
57 //-----------------------------------------------------------------------------
vtkX3DExporterXMLWriter()58 vtkX3DExporterXMLWriter::vtkX3DExporterXMLWriter()
59 {
60   this->OutputStream = nullptr;
61   this->InfoStack = new vtkX3DExporterXMLNodeInfoStack();
62   this->Depth = 0;
63   this->ActTab = "";
64 }
65 
66 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)67 void vtkX3DExporterXMLWriter::PrintSelf(ostream& os, vtkIndent indent)
68 {
69   this->Superclass::PrintSelf(os, indent);
70 }
71 
72 //----------------------------------------------------------------------------
OpenFile(const char * file)73 int vtkX3DExporterXMLWriter::OpenFile(const char* file)
74 {
75   this->CloseFile();
76   this->WriteToOutputString = 0;
77   std::fstream* fileStream = new std::fstream();
78   fileStream->open (file, ios::out);
79   if(fileStream->fail())
80   {
81     delete fileStream;
82     return 0;
83   }
84   else
85   {
86     this->OutputStream = fileStream;
87     return 1;
88   }
89 }
90 
91 //----------------------------------------------------------------------------
OpenStream()92 int vtkX3DExporterXMLWriter::OpenStream()
93 {
94   this->CloseFile();
95 
96   this->WriteToOutputString = 1;
97   this->OutputStream = new std::ostringstream();
98   return 1;
99 }
100 
101 //----------------------------------------------------------------------------
CloseFile()102 void vtkX3DExporterXMLWriter::CloseFile()
103 {
104   if(this->OutputStream != nullptr)
105   {
106     if(this->WriteToOutputString)
107     {
108       std::ostringstream *ostr =
109         static_cast<std::ostringstream*>(this->OutputStream);
110 
111       delete [] this->OutputString;
112       this->OutputStringLength = static_cast<int>(ostr->str().size());
113       this->OutputString = new char[ostr->str().size()];
114       memcpy(this->OutputString, ostr->str().c_str(),
115              this->OutputStringLength);
116     }
117 
118     delete this->OutputStream;
119     this->OutputStream = nullptr;
120   }
121 }
122 
123 //-----------------------------------------------------------------------------
StartDocument()124 void vtkX3DExporterXMLWriter::StartDocument()
125 {
126   this->Depth = 0;
127   *this->OutputStream << "<?xml version=\"1.0\" encoding =\"UTF-8\"?>"
128     << endl << endl;
129 }
130 
131 //-----------------------------------------------------------------------------
EndDocument()132 void vtkX3DExporterXMLWriter::EndDocument()
133 {
134   assert(this->Depth == 0);
135 }
136 
137 //-----------------------------------------------------------------------------
StartNode(int elementID)138 void vtkX3DExporterXMLWriter::StartNode(int elementID)
139 {
140   // End last tag, if this is the first child
141   if (!this->InfoStack->empty())
142   {
143     if (!this->InfoStack->back().endTagWritten)
144     {
145       *this->OutputStream << ">" << this->GetNewline();
146       this->InfoStack->back().endTagWritten = true;
147     }
148   }
149 
150   this->InfoStack->push_back(XMLInfo(elementID));
151   *this->OutputStream << this->ActTab << "<" << x3dElementString[elementID];
152   this->AddDepth();
153 }
154 
155 //-----------------------------------------------------------------------------
EndNode()156 void vtkX3DExporterXMLWriter::EndNode()
157 {
158   assert(!this->InfoStack->empty());
159   this->SubDepth();
160   int elementID = this->InfoStack->back().elementId;
161 
162   // There were no childs
163   if (!this->InfoStack->back().endTagWritten)
164   {
165     *this->OutputStream << "/>" << this->GetNewline();
166   }
167   else
168   {
169     *this->OutputStream << this->ActTab << "</" << x3dElementString[elementID]
170       << ">" << this->GetNewline();
171   }
172 
173   this->InfoStack->pop_back();
174 }
175 
176 //-----------------------------------------------------------------------------
SetField(int attributeID,int type,const double * d)177 void vtkX3DExporterXMLWriter::SetField(int attributeID, int type, const double* d)
178 {
179   *this->OutputStream << " " << x3dAttributeString[attributeID] << "=\"";
180   switch (type)
181   {
182     case(SFVEC3F):
183     case(SFCOLOR):
184       *this->OutputStream << d[0]
185                          << " "
186                          << d[1]
187                          << " "
188                          << d[2];
189       break;
190     case(SFROTATION):
191       *this->OutputStream << d[1]
192                          << " "
193                          << d[2]
194                          << " "
195                          << d[3]
196                          << " "
197                          << vtkMath::RadiansFromDegrees( -d[0] );
198       break;
199     default:
200       *this->OutputStream << "UNKNOWN DATATYPE";
201   }
202   *this->OutputStream << "\"";
203 }
204 
205 //-----------------------------------------------------------------------------
SetField(int attributeID,int type,vtkDataArray * a)206 void vtkX3DExporterXMLWriter::SetField(int attributeID, int type, vtkDataArray* a)
207 {
208   *this->OutputStream << " " << x3dAttributeString[attributeID] << "=\"" << this->GetNewline();
209   switch (type)
210   {
211     case(MFVEC3F):
212       for (vtkIdType i = 0; i < a->GetNumberOfTuples(); i++)
213       {
214         double* d = a->GetTuple(i);
215         *this->OutputStream << this->ActTab << d[0] << " " << d[1] << " " << d[2] << "," << this->GetNewline();
216       }
217       break;
218     case(MFVEC2F):
219       for (vtkIdType i = 0; i < a->GetNumberOfTuples(); i++)
220       {
221         double* d = a->GetTuple(i);
222         *this->OutputStream << this->ActTab << d[0] << " " << d[1] << "," << this->GetNewline();
223       }
224       break;
225     default:
226       *this->OutputStream << "UNKNOWN DATATYPE";
227   }
228     *this->OutputStream << this->ActTab << "\"";
229 }
230 
231 //-----------------------------------------------------------------------------
SetField(int attributeID,const double * values,size_t size)232 void vtkX3DExporterXMLWriter::SetField(int attributeID, const double* values, size_t size)
233 {
234   *this->OutputStream << " " << x3dAttributeString[attributeID] << "=\"" << this->GetNewline() << this->ActTab;
235 
236   unsigned int i = 0;
237   while (i < size)
238   {
239     *this->OutputStream << values[i];
240     if ((i+1)%3)
241     {
242       *this->OutputStream << " ";
243     }
244     else
245     {
246       *this->OutputStream << "," << this->GetNewline() << this->ActTab;
247     }
248     i++;
249   }
250   *this->OutputStream  << "\"";
251 }
252 
253 //-----------------------------------------------------------------------------
SetField(int attributeID,const int * values,size_t size,bool image)254 void vtkX3DExporterXMLWriter::SetField(int attributeID, const int* values, size_t size, bool image)
255 {
256   *this->OutputStream << " " << x3dAttributeString[attributeID] << "=\"" << this->GetNewline() << this->ActTab;
257 
258   unsigned int i = 0;
259   if (image)
260   {
261     assert(size > 2);
262     char buffer[20];
263     *this->OutputStream << values[0] << " "; // width
264     *this->OutputStream << values[1] << " "; // height
265     int bpp = values[2]; *this->OutputStream << bpp << "\n"; // bpp
266 
267     i = 3;
268     unsigned int j = 0;
269 
270     while (i < size)
271     {
272       snprintf(buffer,sizeof(buffer),"0x%.8x",values[i]);
273       *this->OutputStream << buffer;
274 
275       if (j%(8*bpp))
276       {
277         *this->OutputStream << " ";
278       }
279       else
280       {
281         *this->OutputStream << this->GetNewline();// << this->ActTab;
282       }
283       i++; j+=bpp;
284     }
285     *this->OutputStream << dec;
286   }
287   else
288     while (i < size)
289     {
290     *this->OutputStream << values[i] << " ";
291     if (values[i] == -1)
292     {
293       *this->OutputStream << this->GetNewline() << this->ActTab;
294     }
295     i++;
296     }
297   *this->OutputStream  << "\"";
298 }
299 
300 //-----------------------------------------------------------------------------
SetField(int attributeID,int value)301 void vtkX3DExporterXMLWriter::SetField(int attributeID, int value)
302 {
303   *this->OutputStream << " " << x3dAttributeString[attributeID] << "=\"" << value << "\"";
304 }
305 
306 //-----------------------------------------------------------------------------
SetField(int attributeID,float value)307 void vtkX3DExporterXMLWriter::SetField(int attributeID, float value)
308 {
309   *this->OutputStream << " " << x3dAttributeString[attributeID] << "=\"" << value << "\"";
310 }
311 
312 //-----------------------------------------------------------------------------
SetField(int attributeID,double vtkNotUsed (value))313 void vtkX3DExporterXMLWriter::SetField(int attributeID, double vtkNotUsed(value))
314 {
315   *this->OutputStream << " " << x3dAttributeString[attributeID] << "=\"" << "WHY DOUBLE?" << "\"";
316   assert(false);
317 }
318 
319 //-----------------------------------------------------------------------------
SetField(int attributeID,bool value)320 void vtkX3DExporterXMLWriter::SetField(int attributeID, bool value)
321 {
322   *this->OutputStream << " "
323     << x3dAttributeString[attributeID] << "=\"" << (value  ? "true" : "false" ) << "\"";
324 }
325 
326 //-----------------------------------------------------------------------------
SetField(int attributeID,const char * value,bool mfstring)327 void vtkX3DExporterXMLWriter::SetField(int attributeID, const char* value, bool mfstring)
328 {
329   if (mfstring)
330   {
331     *this->OutputStream << " "
332       << x3dAttributeString[attributeID] << "='" << value << "'";
333   }
334   else
335   {
336     *this->OutputStream
337       << " " << x3dAttributeString[attributeID] << "=\"" << value << "\"";
338   }
339 }
340 
341 
342 //-----------------------------------------------------------------------------
Flush()343 void vtkX3DExporterXMLWriter::Flush()
344 {
345   this->OutputStream->flush();
346 }
347 
348 //-----------------------------------------------------------------------------
AddDepth()349 void vtkX3DExporterXMLWriter::AddDepth()
350 {
351   this->ActTab += "  ";
352 }
353 
354 //-----------------------------------------------------------------------------
SubDepth()355 void vtkX3DExporterXMLWriter::SubDepth()
356 {
357   this->ActTab.erase(0, 2);
358 }
359 
360