KiCad PCB EDA Suite
vrml2_transform.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_transform.h"
30 #include "plugins/3dapi/ifsg_all.h"
31 
32 
34 {
36  return;
37 }
38 
39 
41 {
43  m_Parent = aParent;
44 
45  if( NULL != m_Parent )
46  m_Parent->AddChildNode( this );
47 
48  return;
49 }
50 
51 
53 {
54  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
55  do {
56  std::ostringstream ostr;
57  ostr << " * [INFO] Destroying Transform with " << m_Children.size();
58  ostr << " children, " << m_Refs.size() << " references and ";
59  ostr << m_BackPointers.size() << " backpointers";
60  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
61  } while( 0 );
62  #endif
63 
64  return;
65 }
66 
67 
69 {
70  // a Transform node is never dangling
71  return false;
72 }
73 
74 
75 // functions inherited from WRL2NODE
76 bool WRL2TRANSFORM::Read( WRLPROC& proc, WRL2BASE* aTopNode )
77 {
78  /*
79  * Structure of a Transform node (p.120):
80  *
81  * Transform {
82  * eventIn MFNode addChildren
83  * eventIn MFNode removeChildren
84  * exposedField SFVec3f center 0 0 0
85  * exposedField MFNode children []
86  * exposedField SFRotation rotation 0 0 1 0
87  * exposedField SFVec3f scale 1 1 1
88  * exposedField SFRotation scaleOrientation 0 0 1 0
89  * exposedField SFVec3f translation 0 0 0
90  * field SFVec3f bboxCenter 0 0 0
91  * field SFVec3f bboxSize 0 0 0
92  * }
93  */
94 
95  if( NULL == aTopNode )
96  {
97  #ifdef DEBUG_VRML2
98  do {
99  std::ostringstream ostr;
100  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
101  ostr << " * [BUG] aTopNode is NULL";
102  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
103  } while( 0 );
104  #endif
105 
106  return false;
107  }
108 
109  center.x = 0.0;
110  center.y = 0.0;
111  center.z = 0.0;
112 
114  bboxCenter = center;
115  bboxSize = center;
116 
117  rotation.x = 0.0;
118  rotation.y = 0.0;
119  rotation.z = 1.0;
120  rotation.w = 0.0;
121 
123 
124  scale.x = 1.0;
125  scale.y = 1.0;
126  scale.z = 1.0;
127 
128  size_t line, column;
129  proc.GetFilePosData( line, column );
130 
131  char tok = proc.Peek();
132 
133  if( proc.eof() )
134  {
135  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
136  do {
137  std::ostringstream ostr;
138  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
139  ostr << " * [INFO] bad file format; unexpected eof at line ";
140  ostr << line << ", column " << column;
141  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
142  } while( 0 );
143  #endif
144 
145  return false;
146  }
147 
148  if( '{' != tok )
149  {
150  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
151  do {
152  std::ostringstream ostr;
153  ostr << proc.GetError() << "\n";
154  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
155  ostr << " * [INFO] bad file format; expecting '{' but got '" << tok;
156  ostr << "' at line " << line << ", column " << column;
157  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
158  } while( 0 );
159  #endif
160 
161  return false;
162  }
163 
164  proc.Pop();
165  std::string glob;
166 
167  while( true )
168  {
169  if( proc.Peek() == '}' )
170  {
171  proc.Pop();
172  break;
173  }
174 
175  if( !proc.ReadName( glob ) )
176  {
177  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
178  do {
179  std::ostringstream ostr;
180  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
181  ostr << proc.GetError();
182  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
183  } while( 0 );
184  #endif
185 
186  return false;
187  }
188 
189  // expecting one of:
190  // center
191  // children
192  // rotation
193  // scale
194  // ScaleOrientation
195  // translation
196 
197  proc.GetFilePosData( line, column );
198 
199  if( !glob.compare( "center" ) )
200  {
201  if( !proc.ReadSFVec3f( center ) )
202  {
203  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
204  do {
205  std::ostringstream ostr;
206  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
207  ostr << " * [INFO] invalid center at line " << line << ", column ";
208  ostr << column << "\n";
209  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
210  ostr << " * [INFO] message: '" << proc.GetError() << "'";
211  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
212  } while( 0 );
213  #endif
214 
215  return false;
216  }
217 
218  // convert from 1 VRML Unit = 0.1 inch to 1 VRML Unit = 1 mm
219  center.x *= 2.54f;
220  center.y *= 2.54f;
221  center.z *= 2.54f;
222  }
223  else if( !glob.compare( "rotation" ) )
224  {
225  if( !proc.ReadSFRotation( rotation ) )
226  {
227  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
228  do {
229  std::ostringstream ostr;
230  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
231  ostr << " * [INFO] invalid rotation at line " << line << ", column ";
232  ostr << column << "\n";
233  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
234  ostr << " * [INFO] message: '" << proc.GetError() << "'";
235  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
236  } while( 0 );
237  #endif
238 
239  return false;
240  }
241  }
242  else if( !glob.compare( "scale" ) )
243  {
244  if( !proc.ReadSFVec3f( scale ) )
245  {
246  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
247  do {
248  std::ostringstream ostr;
249  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
250  ostr << " * [INFO] invalid scale at line " << line << ", column ";
251  ostr << column << "\n";
252  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
253  ostr << " * [INFO] message: '" << proc.GetError() << "'";
254  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
255  } while( 0 );
256  #endif
257 
258  return false;
259  }
260  }
261  else if( !glob.compare( "scaleOrientation" ) )
262  {
263  if( !proc.ReadSFRotation( scaleOrientation ) )
264  {
265  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
266  do {
267  std::ostringstream ostr;
268  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
269  ostr << " * [INFO] invalid scaleOrientation at line " << line << ", column ";
270  ostr << column << "\n";
271  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
272  ostr << " * [INFO] message: '" << proc.GetError() << "'";
273  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
274  } while( 0 );
275  #endif
276 
277  return false;
278  }
279  }
280  else if( !glob.compare( "translation" ) )
281  {
282  if( !proc.ReadSFVec3f( translation ) )
283  {
284  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
285  do {
286  std::ostringstream ostr;
287  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
288  ostr << " * [INFO] invalid translation at line " << line << ", column ";
289  ostr << column << "\n";
290  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
291  ostr << " * [INFO] message: '" << proc.GetError() << "'";
292  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
293  } while( 0 );
294  #endif
295 
296  return false;
297  }
298 
299  // convert from 1 VRML Unit = 0.1 inch to 1 VRML Unit = 1 mm
300  translation.x *= 2.54f;
301  translation.y *= 2.54f;
302  translation.z *= 2.54f;
303  }
304  else if( !glob.compare( "children" ) )
305  {
306  if( !readChildren( proc, aTopNode ) )
307  return false;
308  }
309  else
310  {
311  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
312  do {
313  std::ostringstream ostr;
314  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
315  ostr << " * [INFO] bad Transform at line " << line << ", column ";
316  ostr << column << "\n";
317  ostr << " * [INFO] file: '" << proc.GetFileName() << "'";
318  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
319  } while( 0 );
320  #endif
321 
322  return false;
323  }
324  } // while( true ) -- reading contents of Transform{}
325 
326  return true;
327 }
328 
329 
331 {
332  if( NULL == aNode )
333  {
334  #ifdef DEBUG_VRML2
335  do {
336  std::ostringstream ostr;
337  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
338  ostr << " * [BUG] NULL passed as node pointer";
339  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
340  } while( 0 );
341  #endif
342 
343  return false;
344  }
345 
346  // take possession if the node is dangling WRL2_SHAPE
347 
348  if( WRL2_SHAPE == aNode->GetNodeType() && aNode->isDangling() )
349  {
350  WRL2NODE* np = aNode->GetParent();
351 
352  if( NULL != np )
353  aNode->SetParent( this );
354 
355 
356  if( !WRL2NODE::AddChildNode( aNode ) )
357  {
358  aNode->SetParent( NULL );
359  return false;
360  }
361  }
362 
363  if( !WRL2NODE::AddRefNode( aNode ) )
364  return false;
365 
366  return true;
367 }
368 
369 
371 {
372  size_t line, column;
373  proc.GetFilePosData( line, column );
374 
375  char tok = proc.Peek();
376 
377  if( proc.eof() )
378  {
379  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
380  do {
381  std::ostringstream ostr;
382  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
383  ostr << " * [INFO] bad file format; unexpected eof at line ";
384  ostr << line << ", column " << column;
385  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
386  } while( 0 );
387  #endif
388 
389  return false;
390  }
391 
392  if( '[' != tok )
393  {
394  // since there are no delimeters we expect a single child
395  if( !aTopNode->ReadNode( proc, this, NULL ) )
396  return false;
397 
398  if( proc.Peek() == ',' )
399  proc.Pop();
400 
401  return true;
402  }
403 
404  proc.Pop();
405 
406  while( true )
407  {
408  if( proc.Peek() == ']' )
409  {
410  proc.Pop();
411  break;
412  }
413 
414  if( !aTopNode->ReadNode( proc, this, NULL ) )
415  return false;
416 
417  if( proc.Peek() == ',' )
418  proc.Pop();
419 
420  }
421 
422  return true;
423 }
424 
425 
427 {
428  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
429  do {
430  std::ostringstream ostr;
431  ostr << " * [INFO] Translating Transform with " << m_Children.size();
432  ostr << " children, " << m_Refs.size() << " references and ";
433  ostr << m_BackPointers.size() << " backpointers";
434  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
435  } while( 0 );
436  #endif
437 
438  if( m_Children.empty() && m_Refs.empty() )
439  return NULL;
440 
441  S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
442 
443  if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
444  {
445  #ifdef DEBUG_VRML2
446  do {
447  std::ostringstream ostr;
448  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
449  ostr << " * [BUG] Transform does not have a Transform parent (parent ID: ";
450  ostr << ptype << ")";
451  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
452  } while( 0 );
453  #endif
454 
455  return NULL;
456  }
457 
458  if( m_sgNode )
459  {
460  if( NULL != aParent )
461  {
463  && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
464  {
465  return NULL;
466  }
467  else if( aParent != S3D::GetSGNodeParent( m_sgNode )
468  && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
469  {
470  return NULL;
471  }
472  }
473 
474  return m_sgNode;
475  }
476 
477  IFSG_TRANSFORM txNode( aParent );
478 
479  std::list< WRL2NODE* >::iterator sC = m_Children.begin();
480  std::list< WRL2NODE* >::iterator eC = m_Children.end();
481  WRL2NODES type;
482 
483  // Include only the following in a Transform node:
484  // Shape
485  // Switch
486  // Transform
487  // Inline
488  bool test = false; // set to true if there are any subnodes for display
489 
490  for( int i = 0; i < 2; ++i )
491  {
492  while( sC != eC )
493  {
494  type = (*sC)->GetNodeType();
495 
496  switch( type )
497  {
498  case WRL2_SHAPE:
499  case WRL2_SWITCH:
500  case WRL2_INLINE:
501  case WRL2_TRANSFORM:
502 
503  if( NULL != (*sC)->TranslateToSG( txNode.GetRawPtr() ) )
504  test = true;
505 
506  break;
507 
508  default:
509  break;
510  }
511 
512  ++ sC;
513  }
514 
515  sC = m_Refs.begin();
516  eC = m_Refs.end();
517  }
518 
519  if( false == test )
520  {
521  txNode.Destroy();
522  return NULL;
523  }
524 
525  txNode.SetScale( SGPOINT( scale.x, scale.y, scale.z ) );
526  txNode.SetCenter( SGPOINT( center.x, center.y, center.z ) );
530  txNode.SetRotation( SGVECTOR( rotation.x, rotation.y, rotation.z), rotation.w );
531 
532  m_sgNode = txNode.GetRawPtr();
533 
534  return m_sgNode;
535 }
bool ReadSFRotation(WRLROTATION &aSFRotation)
Definition: wrlproc.cpp:920
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
WRLROTATION rotation
std::list< WRL2NODE * > m_Children
Definition: vrml2_node.h:66
bool GetFilePosData(size_t &line, size_t &column)
Definition: wrlproc.cpp:1951
bool ReadSFVec3f(WRLVEC3F &aSFVec3f)
Definition: wrlproc.cpp:1065
#define MASK_VRML
Definition: wrltypes.h:37
std::list< WRL2NODE * > m_Refs
Definition: vrml2_node.h:67
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:636
bool readChildren(WRLPROC &proc, WRL2BASE *aTopNode)
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
SGNODE * GetRawPtr(void) noexcept
Function GetRawPtr() returns the raw internal SGNODE pointer.
Definition: ifsg_node.cpp:66
bool AddRefNode(WRL2NODE *aNode) override
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:645
bool ReadNode(WRLPROC &proc, WRL2NODE *aParent, WRL2NODE **aNode)
Definition: vrml2_base.cpp:371
bool SetScaleOrientation(const SGVECTOR &aScaleAxis, double aAngle)
virtual ~WRL2TRANSFORM()
#define NULL
bool Read(WRLPROC &proc, WRL2BASE *aTopNode) override
WRL2NODE * m_Parent
Definition: vrml2_node.h:61
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:654
SGNODE * m_sgNode
Definition: vrml2_node.h:70
bool SetRotation(const SGVECTOR &aRotationAxis, double aAngle)
std::list< WRL2NODE * > m_BackPointers
Definition: vrml2_node.h:65
SGNODE * TranslateToSG(SGNODE *aParent) override
Function TranslateToSG produces a representation of the data using the intermediate scenegraph struct...
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
SGTYPES
Definition: sg_types.h:34
WRLROTATION scaleOrientation
virtual bool isDangling(void)=0
Function isDangling returns true if the object does not have a parent which is a logical container fo...
WRLVEC3F bboxCenter
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 SetCenter(const SGPOINT &aCenter) noexcept
IFSG_TRANSFORM is the wrapper for the VRML compatible TRANSFORM block class SCENEGRAPH.
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
bool isDangling(void) override
Function isDangling returns true if the object does not have a parent which is a logical container fo...
bool SetTranslation(const SGPOINT &aTranslation) noexcept
bool SetScale(const SGPOINT &aScale) noexcept
WRL2NODES
Definition: wrltypes.h:121
std::string GetError(void)
Definition: wrlproc.cpp:1945
void Destroy(void)
Function Destroy deletes the object held by this wrapper.
Definition: ifsg_node.cpp:54
virtual bool AddRefNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:416
bool eof(void)
Definition: wrlproc.cpp:1939
WRLVEC3F translation
WRLVEC3F bboxSize