KiCad PCB EDA Suite
vrml2_switch.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <iostream>
25 #include <sstream>
26 #include <wx/log.h>
27 
28 #include "vrml2_base.h"
29 #include "vrml2_switch.h"
30 #include "plugins/3dapi/ifsg_all.h"
31 
32 
34 {
36  whichChoice = -1;
37 
38  return;
39 }
40 
41 
43 {
45  m_Parent = aParent;
46  whichChoice = -1;
47 
48  if( NULL != m_Parent )
49  m_Parent->AddChildNode( this );
50 
51  return;
52 }
53 
54 
56 {
57  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
58  do {
59  std::ostringstream ostr;
60  ostr << " * [INFO] Destroying Switch with " << m_Children.size();
61  ostr << " children, " << m_Refs.size() << " references and ";
62  ostr << m_BackPointers.size() << " backpointers";
63  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
64  } while( 0 );
65  #endif
66 
67  return;
68 }
69 
70 
72 {
73  // a Switch node is never dangling
74  return false;
75 }
76 
77 
78 // functions inherited from WRL2NODE
79 bool WRL2SWITCH::Read( WRLPROC& proc, WRL2BASE* aTopNode )
80 {
81  /*
82  * Structure of a Switch node (p.113):
83  *
84  * Switch {
85  * exposedField MFNode choice []
86  * exposedField SFInt32 whichChoice -1
87  * }
88  */
89 
90  if( NULL == aTopNode )
91  {
92  #ifdef DEBUG_VRML2
93  do {
94  std::ostringstream ostr;
95  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
96  ostr << " * [BUG] aTopNode is NULL";
97  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
98  } while( 0 );
99  #endif
100 
101  return false;
102  }
103 
104  size_t line, column;
105  proc.GetFilePosData( line, column );
106 
107  char tok = proc.Peek();
108 
109  if( proc.eof() )
110  {
111  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
112  do {
113  std::ostringstream ostr;
114  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
115  ostr << " * [INFO] bad file format; unexpected eof at line ";
116  ostr << line << ", column " << column;
117  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
118  } while( 0 );
119  #endif
120 
121  return false;
122  }
123 
124  if( '{' != tok )
125  {
126  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
127  do {
128  std::ostringstream ostr;
129  ostr << proc.GetError() << "\n";
130  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
131  ostr << " * [INFO] bad file format; expecting '{' but got '" << tok;
132  ostr << "' at line " << line << ", column " << column;
133  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
134  } while( 0 );
135  #endif
136 
137  return false;
138  }
139 
140  proc.Pop();
141  std::string glob;
142 
143  while( true )
144  {
145  if( proc.Peek() == '}' )
146  {
147  proc.Pop();
148  break;
149  }
150 
151  if( !proc.ReadName( glob ) )
152  {
153  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
154  do {
155  std::ostringstream ostr;
156  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
157  ostr << proc.GetError();
158  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
159  } while( 0 );
160  #endif
161 
162  return false;
163  }
164 
165  // expecting one of:
166  // choice
167  // whichChoice
168 
169  proc.GetFilePosData( line, column );
170 
171  if( !glob.compare( "whichChoice" ) )
172  {
173  if( !proc.ReadSFInt( whichChoice ) )
174  {
175  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
176  do {
177  std::ostringstream ostr;
178  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
179  ostr << " * [INFO] invalid whichChoice at line " << line << ", column ";
180  ostr << column << "\n";
181  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
182  ostr << " * [INFO] message: '" << proc.GetError() << "'";
183  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
184  } while( 0 );
185  #endif
186 
187  return false;
188  }
189  }
190  else if( !glob.compare( "choice" ) )
191  {
192  if( !readChildren( proc, aTopNode ) )
193  return false;
194  }
195  else
196  {
197  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
198  do {
199  std::ostringstream ostr;
200  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
201  ostr << " * [INFO] bad Switch at line " << line << ", column ";
202  ostr << column << "\n";
203  ostr << " * [INFO] file: '" << proc.GetFileName() << "'";
204  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
205  } while( 0 );
206  #endif
207 
208  return false;
209  }
210  } // while( true ) -- reading contents of Switch{}
211 
212  return true;
213 }
214 
215 
217 {
218  if( NULL == aNode )
219  {
220  #ifdef DEBUG_VRML2
221  do {
222  std::ostringstream ostr;
223  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
224  ostr << " * [BUG] NULL passed as node pointer";
225  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
226  } while( 0 );
227  #endif
228 
229  return false;
230  }
231 
232  // take possession if the node is dangling WRL2_SHAPE
233  if( WRL2_SHAPE == aNode->GetNodeType() && aNode->isDangling() )
234  {
235  WRL2NODE* np = aNode->GetParent();
236 
237  if( NULL != np )
238  aNode->SetParent( this );
239 
240  if( !WRL2NODE::AddChildNode( aNode ) )
241  {
242  aNode->SetParent( NULL );
243  return false;
244  }
245  }
246 
247  if( !WRL2NODE::AddRefNode( aNode ) )
248  return false;
249 
250  return true;
251 }
252 
253 
254 bool WRL2SWITCH::readChildren( WRLPROC& proc, WRL2BASE* aTopNode )
255 {
256  size_t line, column;
257  proc.GetFilePosData( line, column );
258 
259  char tok = proc.Peek();
260 
261  if( proc.eof() )
262  {
263  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
264  do {
265  std::ostringstream ostr;
266  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
267  ostr << " * [INFO] bad file format; unexpected eof at line ";
268  ostr << line << ", column " << column;
269  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
270  } while( 0 );
271  #endif
272 
273  return false;
274  }
275 
276  WRL2NODE* child = NULL;
277 
278  if( '[' != tok )
279  {
280  // since there are no delimeters we expect a single child
281  if( !aTopNode->ReadNode( proc, this, &child ) )
282  return false;
283 
284  if( NULL != child )
285  choices.push_back( child );
286 
287  if( proc.Peek() == ',' )
288  proc.Pop();
289 
290  return true;
291  }
292 
293  proc.Pop();
294 
295  while( true )
296  {
297  if( proc.Peek() == ']' )
298  {
299  proc.Pop();
300  break;
301  }
302 
303  if( !aTopNode->ReadNode( proc, this, &child ) )
304  return false;
305 
306  if( NULL != child )
307  choices.push_back( child );
308 
309  if( proc.Peek() == ',' )
310  proc.Pop();
311 
312  }
313 
314  return true;
315 }
316 
317 
319 {
320  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
321  do {
322  std::ostringstream ostr;
323  ostr << " * [INFO] Translating Switch with " << m_Children.size();
324  ostr << " children, " << m_Refs.size() << " references and ";
325  ostr << m_BackPointers.size() << " backpointers";
326  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
327  } while( 0 );
328  #endif
329 
330  if( choices.empty() )
331  {
332  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
333  wxLogTrace( MASK_VRML, " * [INFO] Switch translation: no choices\n" );
334  #endif
335 
336  return NULL;
337  }
338 
339  S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
340 
341  if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
342  {
343  #ifdef DEBUG_VRML2
344  do {
345  std::ostringstream ostr;
346  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
347  ostr << " * [BUG] Switch does not have a Transform parent (parent ID: ";
348  ostr << ptype << ")";
349  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
350  } while( 0 );
351  #endif
352 
353  return NULL;
354  }
355 
356  if( whichChoice < 0 || whichChoice >= (int)choices.size() )
357  {
358  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
359  do {
360  std::ostringstream ostr;
361  ostr << " * [INFO] Switch translation: no choice (choices = ";
362  ostr << choices.size() << "), whichChoice = " << whichChoice;
363  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
364  } while( 0 );
365  #endif
366 
367  return NULL;
368  }
369 
370  WRL2NODES type = choices[whichChoice]->GetNodeType();
371 
372  switch( type )
373  {
374  case WRL2_SHAPE:
375  case WRL2_SWITCH:
376  case WRL2_INLINE:
377  case WRL2_TRANSFORM:
378  break;
379 
380  default:
381  return NULL;
382  }
383 
384  return choices[whichChoice]->TranslateToSG( aParent );
385 }
virtual bool SetParent(WRL2NODE *aParent, bool doUnlink=true)
Function SetParent sets the parent WRL2NODE of this object.
Definition: vrml2_node.cpp:360
void Pop(void)
Definition: wrlproc.cpp:2007
WRL2NODE represents the base class of all VRML2 nodes.
Definition: vrml2_node.h:58
std::list< WRL2NODE * > m_Children
Definition: vrml2_node.h:66
bool GetFilePosData(size_t &line, size_t &column)
Definition: wrlproc.cpp:1951
#define MASK_VRML
Definition: wrltypes.h:37
bool AddRefNode(WRL2NODE *aNode) override
std::list< WRL2NODE * > m_Refs
Definition: vrml2_node.h:67
WRL2NODES m_Type
Definition: vrml2_node.h:62
SGNODE represents the base class of all Scene Graph nodes.
Definition: sg_node.h:76
collects header files for all SG* wrappers and the API
bool ReadNode(WRLPROC &proc, WRL2NODE *aParent, WRL2NODE **aNode)
Definition: vrml2_base.cpp:371
bool isDangling(void) override
Function isDangling returns true if the object does not have a parent which is a logical container fo...
#define NULL
bool readChildren(WRLPROC &proc, WRL2BASE *aTopNode)
WRL2NODE * m_Parent
Definition: vrml2_node.h:61
std::list< WRL2NODE * > m_BackPointers
Definition: vrml2_node.h:65
WRL2NODES GetNodeType(void) const
Function GetNodeType returns the type of this node instance.
Definition: vrml2_node.cpp:212
char Peek(void)
Definition: wrlproc.cpp:1979
std::string GetFileName(void)
Definition: wrlproc.cpp:1967
WRL2BASE represents the top node of a VRML2 model.
Definition: vrml2_base.h:59
int whichChoice
Definition: vrml2_switch.h:43
bool Read(WRLPROC &proc, WRL2BASE *aTopNode) override
SGTYPES
Definition: sg_types.h:34
virtual ~WRL2SWITCH()
SGNODE * TranslateToSG(SGNODE *aParent) override
Function TranslateToSG produces a representation of the data using the intermediate scenegraph struct...
virtual bool isDangling(void)=0
Function isDangling returns true if the object does not have a parent which is a logical container fo...
SGLIB_API S3D::SGTYPES GetSGNodeType(SGNODE *aNode)
Definition: ifsg_api.cpp:627
virtual bool AddChildNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:377
bool ReadName(std::string &aName)
Definition: wrlproc.cpp:280
bool ReadSFInt(int &aSFInt32)
Definition: wrlproc.cpp:850
WRL2NODE * GetParent(void) const
Function GetParent returns a pointer to the parent SGNODE of this object or NULL if the object has no...
Definition: vrml2_node.cpp:218
WRL2NODES
Definition: wrltypes.h:121
std::string GetError(void)
Definition: wrlproc.cpp:1945
virtual bool AddRefNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:416
bool eof(void)
Definition: wrlproc.cpp:1939
std::vector< WRL2NODE * > choices
Definition: vrml2_switch.h:44