KiCad PCB EDA Suite
x3d_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) 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 
25 #include <iostream>
26 #include <sstream>
27 #include <wx/xml/xml.h>
28 #include <wx/log.h>
29 #include "x3d_ops.h"
30 #include "x3d_transform.h"
31 #include "plugins/3dapi/ifsg_all.h"
32 
33 
35 {
37  init();
38 
39  return;
40 }
41 
43 {
45  init();
46 
47  if( NULL != aParent )
48  {
49  X3DNODES ptype = aParent->GetNodeType();
50 
51  if( X3D_TRANSFORM == ptype || X3D_SWITCH == ptype )
52  m_Parent = aParent;
53  }
54 
55  if( NULL != m_Parent )
56  m_Parent->AddChildNode( this );
57 
58  return;
59 }
60 
61 
63 {
64  #if defined( DEBUG_X3D ) && ( DEBUG_X3D > 2 )
65  do {
66  std::ostringstream ostr;
67  ostr << " * [INFO] Destroying Transform with " << m_Children.size();
68  ostr << " children, " << m_Refs.size() << " references and ";
69  ostr << m_BackPointers.size() << " backpointers";
70  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
71  } while( 0 );
72  #endif
73 
74  return;
75 }
76 
77 
79 {
80  center.x = 0.0;
81  center.y = 0.0;
82  center.z = 0.0;
83 
84  scale.x = 1.0;
85  scale.y = 1.0;
86  scale.z = 1.0;
87 
89 
90  rotation.x = 0.0;
91  rotation.y = 0.0;
92  rotation.z = 1.0;
93 
95 
97  bboxSize = center;
98 
99  return;
100 }
101 
102 
103 void X3DTRANSFORM::readFields( wxXmlNode* aNode )
104 {
105  // DEF
106  // center
107  // scale
108  // translation
109  // rotation
110  // scaleOrientation
111  // bboxCenter (ignored)
112  // bboxSize (ignored)
113 
114  wxXmlAttribute* prop;
115 
116  // note: center/translation are multiplied by 2.54 to retain
117  // legacy behavior of 1 X3D unit = 0.1 inch; the SG*
118  // classes expect all units in mm.
119 
120  for( prop = aNode->GetAttributes();
121  prop != NULL;
122  prop = prop->GetNext() )
123  {
124  const wxString& pname = prop->GetName();
125 
126  if( pname == "DEF" )
127  {
128  m_Name = prop->GetValue();
129  m_Dict->AddName( m_Name, this );
130  }
131  else if( pname == "center" )
132  {
133  X3D::ParseSFVec3( prop->GetValue(), center );
134  center *= 2.54;
135  }
136  else if( pname == "scale" )
137  X3D::ParseSFVec3( prop->GetValue(), scale );
138  else if( pname == "translation" )
139  {
140  X3D::ParseSFVec3( prop->GetValue(), translation );
141  translation *= 2.54;
142  }
143  else if( pname == "rotation" )
144  X3D::ParseSFRotation( prop->GetValue(), rotation );
145  else if( pname == "scaleOrientation" )
146  X3D::ParseSFRotation( prop->GetValue(), scaleOrientation );
147 
148  }
149 
150  return;
151 }
152 
153 
154 bool X3DTRANSFORM::Read( wxXmlNode* aNode, X3DNODE* aTopNode, X3D_DICT& aDict )
155 {
156  if( NULL == aTopNode || NULL == aNode )
157  return false;
158 
159  m_Dict = &aDict;
160  readFields( aNode );
161  bool ok = false;
162 
163  for( wxXmlNode* child = aNode->GetChildren();
164  child != NULL;
165  child = child->GetNext() )
166  {
167  wxString name = child->GetName();
168 
169  if( name == "Transform" || name == "Group" )
170  ok |= X3D::ReadTransform( child, this, aDict );
171  else if( name == "Switch" )
172  ok |= X3D::ReadSwitch( child, this, aDict );
173  else if( name == "Shape" )
174  ok |= X3D::ReadShape( child, this, aDict );
175 
176  }
177 
178  if( !ok )
179  return false;
180 
181  if( !SetParent( aTopNode ) )
182  return false;
183 
184  return true;
185 }
186 
187 
188 bool X3DTRANSFORM::SetParent( X3DNODE* aParent, bool doUnlink )
189 {
190  if( aParent == m_Parent )
191  return true;
192 
193  if( NULL != aParent )
194  {
195  X3DNODES nt = aParent->GetNodeType();
196 
197  if( nt != X3D_SWITCH && nt != X3D_TRANSFORM )
198  return false;
199  }
200 
201  if( NULL != m_Parent && doUnlink )
202  m_Parent->unlinkChildNode( this );
203 
204  m_Parent = aParent;
205 
206  if( NULL != m_Parent )
207  m_Parent->AddChildNode( this );
208 
209  return true;
210 }
211 
212 
214 {
215  if( NULL == aNode )
216  return false;
217 
218  X3DNODES tchild = aNode->GetNodeType();
219 
220  if( X3D_SWITCH != tchild && X3D_TRANSFORM != tchild && X3D_SHAPE != tchild )
221  return false;
222 
223  std::list< X3DNODE* >::iterator sC = m_Children.begin();
224  std::list< X3DNODE* >::iterator eC = m_Children.end();
225 
226  while( sC != eC )
227  {
228  if( *sC == aNode )
229  return false;
230 
231  ++sC;
232  }
233 
234  m_Children.push_back( aNode );
235 
236  if( aNode->GetParent() != this )
237  aNode->SetParent( this );
238 
239  return true;
240 }
241 
242 
244 {
245  if( NULL == aNode )
246  return false;
247 
248  X3DNODES tchild = aNode->GetNodeType();
249 
250  if( X3D_SWITCH != tchild && X3D_TRANSFORM != tchild && X3D_SHAPE != tchild )
251  return false;
252 
253  std::list< X3DNODE* >::iterator sR = m_Refs.begin();
254  std::list< X3DNODE* >::iterator eR = m_Refs.end();
255 
256  while( sR != eR )
257  {
258  if( *sR == aNode )
259  return true;
260 
261  ++sR;
262  }
263 
264  m_Refs.push_back( aNode );
265  aNode->addNodeRef( this );
266 
267  return true;
268 }
269 
270 
272 {
273  #if defined( DEBUG_X3D ) && ( DEBUG_X3D > 2 )
274  do {
275  std::ostringstream ostr;
276  ostr << " * [INFO] Translating Transform with " << m_Children.size();
277  ostr << " children, " << m_Refs.size() << " references and ";
278  ostr << m_BackPointers.size() << " backpointers";
279  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
280  } while( 0 );
281  #endif
282 
283  if( m_Children.empty() && m_Refs.empty() )
284  return NULL;
285 
286  S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
287 
288  if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
289  {
290  #ifdef DEBUG_X3D
291  do {
292  std::ostringstream ostr;
293  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
294  ostr << " * [BUG] Transform does not have a Transform parent (parent ID: ";
295  ostr << ptype << ")";
296  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
297  } while( 0 );
298  #endif
299 
300  return NULL;
301  }
302 
303  if( m_sgNode )
304  {
305  if( NULL != aParent )
306  {
308  && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
309  {
310  return NULL;
311  }
312  else if( aParent != S3D::GetSGNodeParent( m_sgNode )
313  && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
314  {
315  return NULL;
316  }
317  }
318 
319  return m_sgNode;
320  }
321 
322  IFSG_TRANSFORM txNode( aParent );
323 
324  std::list< X3DNODE* >::iterator sC = m_Children.begin();
325  std::list< X3DNODE* >::iterator eC = m_Children.end();
326  X3DNODES type;
327 
328  // Include only the following in a Transform node:
329  // Shape
330  // Switch
331  // Transform
332  // Inline
333  bool test = false; // set to true if there are any subnodes for display
334 
335  for( int i = 0; i < 2; ++i )
336  {
337  while( sC != eC )
338  {
339  type = (*sC)->GetNodeType();
340 
341  switch( type )
342  {
343  case X3D_SHAPE:
344  case X3D_SWITCH:
345  case X3D_TRANSFORM:
346 
347  if( NULL != (*sC)->TranslateToSG( txNode.GetRawPtr() ) )
348  test = true;
349 
350  break;
351 
352  default:
353  break;
354  }
355 
356  ++ sC;
357  }
358 
359  sC = m_Refs.begin();
360  eC = m_Refs.end();
361  }
362 
363  if( false == test )
364  {
365  txNode.Destroy();
366  return NULL;
367  }
368 
369  txNode.SetScale( SGPOINT( scale.x, scale.y, scale.z ) );
370  txNode.SetCenter( SGPOINT( center.x, center.y, center.z ) );
374  txNode.SetRotation( SGVECTOR( rotation.x, rotation.y, rotation.z), rotation.w );
375 
376  m_sgNode = txNode.GetRawPtr();
377 
378  return m_sgNode;
379 }
WRLVEC3F translation
Definition: x3d_transform.h:46
virtual bool SetParent(X3DNODE *aParent, bool doUnlink=true)=0
Function SetParent sets the parent X3DNODE of this object.
SGNODE * TranslateToSG(SGNODE *aParent) override
Function TranslateToSG produces a representation of the data using the intermediate scenegraph struct...
std::list< X3DNODE * > m_BackPointers
Definition: x3d_base.h:82
bool AddChildNode(X3DNODE *aNode) override
#define MASK_VRML
Definition: wrltypes.h:37
X3DNODES m_Type
Definition: x3d_base.h:79
X3DNODE * GetParent(void) const
Function GetParent returns a pointer to the parent node of this object or NULL if the object has no p...
Definition: x3d_base.cpp:192
wxString m_Name
Definition: x3d_base.h:87
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:636
bool Read(wxXmlNode *aNode, X3DNODE *aTopNode, X3D_DICT &aDict) override
void addNodeRef(X3DNODE *aNode)
Function addNodeRef adds a pointer to a node which references, but does not own, this node.
Definition: x3d_base.cpp:141
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 ReadTransform(wxXmlNode *aNode, X3DNODE *aParent, X3D_DICT &aDict)
Definition: x3d_ops.cpp:33
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:645
std::list< X3DNODE * > m_Children
Definition: x3d_base.h:83
bool SetScaleOrientation(const SGVECTOR &aScaleAxis, double aAngle)
X3DNODE represents the base class of all X3D nodes.
Definition: x3d_base.h:75
WRLVEC3F bboxSize
Definition: x3d_transform.h:50
WRLVEC3F scale
Definition: x3d_transform.h:45
#define NULL
bool AddRefNode(X3DNODE *aNode) override
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:654
bool SetRotation(const SGVECTOR &aRotationAxis, double aAngle)
void readFields(wxXmlNode *aNode)
virtual bool AddChildNode(X3DNODE *aNode)=0
X3DNODES GetNodeType(void) const
Function GetNodeType returns the type of this node instance.
Definition: x3d_base.cpp:186
virtual void unlinkChildNode(const X3DNODE *aNode)
Function unlinkChild removes references to an owned child; it is invoked by the child upon destructio...
Definition: x3d_base.cpp:101
WRLROTATION scaleOrientation
Definition: x3d_transform.h:48
WRLROTATION rotation
Definition: x3d_transform.h:47
bool AddName(const wxString &aName, X3DNODE *aNode)
Definition: x3d_base.cpp:34
bool ParseSFRotation(const wxString &aSource, WRLROTATION &aResult)
Definition: x3d_ops.cpp:293
SGTYPES
Definition: sg_types.h:34
bool ReadShape(wxXmlNode *aNode, X3DNODE *aParent, X3D_DICT &aDict)
Definition: x3d_ops.cpp:80
virtual ~X3DTRANSFORM()
SGNODE * m_sgNode
Definition: x3d_base.h:88
SGLIB_API S3D::SGTYPES GetSGNodeType(SGNODE *aNode)
Definition: ifsg_api.cpp:627
X3DNODE * m_Parent
Definition: x3d_base.h:78
const char * name
Definition: DXF_plotter.cpp:60
bool SetCenter(const SGPOINT &aCenter) noexcept
IFSG_TRANSFORM is the wrapper for the VRML compatible TRANSFORM block class SCENEGRAPH.
bool ParseSFVec3(const wxString &aSource, WRLVEC3F &aResult)
Definition: x3d_ops.cpp:273
bool SetTranslation(const SGPOINT &aTranslation) noexcept
bool ReadSwitch(wxXmlNode *aNode, X3DNODE *aParent, X3D_DICT &aDict)
Definition: x3d_ops.cpp:73
bool SetScale(const SGPOINT &aScale) noexcept
WRLVEC3F bboxCenter
Definition: x3d_transform.h:49
void Destroy(void)
Function Destroy deletes the object held by this wrapper.
Definition: ifsg_node.cpp:54
bool SetParent(X3DNODE *aParent, bool doUnlink=true) override
Function SetParent sets the parent X3DNODE of this object.
X3DNODES
Definition: x3d_base.h:59
X3D_DICT * m_Dict
Definition: x3d_base.h:80
WRLVEC3F center
Definition: x3d_transform.h:44
std::list< X3DNODE * > m_Refs
Definition: x3d_base.h:84