KiCad PCB EDA Suite
x3d_shape.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_shape.h"
31 #include "plugins/3dapi/ifsg_all.h"
32 
33 
35 {
36  m_Type = X3D_SHAPE;
37  appearance = NULL;
38  geometry = NULL;
39 
40  return;
41 }
42 
43 
45 {
46  m_Type = X3D_SHAPE;
47  appearance = NULL;
48  geometry = NULL;
49 
50  if( NULL != aParent )
51  {
52  X3DNODES ptype = aParent->GetNodeType();
53 
54  if( X3D_TRANSFORM == ptype || X3D_SWITCH == ptype )
55  m_Parent = aParent;
56  }
57 
58  if( NULL != m_Parent )
59  m_Parent->AddChildNode( this );
60 
61  return;
62 }
63 
64 
66 {
67  #if defined( DEBUG_X3D ) && ( DEBUG_X3D > 2 )
68  do {
69  std::ostringstream ostr;
70  ostr << " * [INFO] Destroying Shape with " << m_Children.size();
71  ostr << " children, " << m_Refs.size() << " references and ";
72  ostr << m_BackPointers.size() << " backpointers";
73  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
74  } while( 0 );
75  #endif
76 
77  return;
78 }
79 
80 
81 bool X3DSHAPE::Read( wxXmlNode* aNode, X3DNODE* aTopNode, X3D_DICT& aDict )
82 {
83  if( NULL == aTopNode || NULL == aNode )
84  return false;
85 
86  if( NULL != appearance || NULL != geometry )
87  return false;
88 
89  m_Dict = &aDict;
90  wxXmlAttribute* prop;
91 
92  for( prop = aNode->GetAttributes();
93  prop != NULL;
94  prop = prop->GetNext() )
95  {
96  const wxString& pname = prop->GetName();
97 
98  if( pname == "DEF" )
99  {
100  m_Name = prop->GetValue();
101  m_Dict->AddName( m_Name, this );
102  }
103  }
104 
105  for( wxXmlNode* child = aNode->GetChildren();
106  child != NULL;
107  child = child->GetNext() )
108  {
109  wxString name = child->GetName();
110 
111  if( name == "Appearance" && NULL == appearance )
112  X3D::ReadAppearance( child, this, aDict );
113  else if( name == "IndexedFaceSet" && NULL == geometry )
114  X3D::ReadIndexedFaceSet( child, this, aDict );
115 
116  }
117 
118  if( NULL == appearance || NULL == geometry )
119  return false;
120 
121  if( !SetParent( aTopNode ) )
122  return false;
123 
124  return true;
125 }
126 
127 
128 bool X3DSHAPE::SetParent( X3DNODE* aParent, bool doUnlink )
129 {
130  if( aParent == m_Parent )
131  return true;
132 
133  if( NULL != aParent )
134  {
135  X3DNODES nt = aParent->GetNodeType();
136 
137  if( nt != X3D_SWITCH && nt != X3D_TRANSFORM )
138  return false;
139  }
140 
141  if( NULL != m_Parent && doUnlink )
142  m_Parent->unlinkChildNode( this );
143 
144  m_Parent = aParent;
145 
146  if( NULL != m_Parent )
147  m_Parent->AddChildNode( this );
148 
149  return true;
150 }
151 
152 
154 {
155  if( NULL == aNode )
156  return false;
157 
158  X3DNODES tchild = aNode->GetNodeType();
159 
160  if( X3D_APPEARANCE != tchild && X3D_INDEXED_FACE_SET != tchild )
161  return false;
162 
163  std::list< X3DNODE* >::iterator sC = m_Children.begin();
164  std::list< X3DNODE* >::iterator eC = m_Children.end();
165 
166  while( sC != eC )
167  {
168  if( *sC == aNode )
169  return false;
170 
171  ++sC;
172  }
173 
174  if( X3D_APPEARANCE == tchild )
175  {
176  if( NULL == appearance )
177  {
178  m_Children.push_back( aNode );
179  appearance = aNode;
180  }
181  else
182  return false;
183  }
184  else
185  {
186  if( NULL == geometry )
187  {
188  m_Children.push_back( aNode );
189  geometry = aNode;
190  }
191  else
192  return false;
193  }
194 
195  if( aNode->GetParent() != this )
196  aNode->SetParent( this );
197 
198  return true;
199 }
200 
201 
203 {
204  if( NULL == aNode )
205  return false;
206 
207  X3DNODES tchild = aNode->GetNodeType();
208 
209  if( X3D_APPEARANCE != tchild && X3D_INDEXED_FACE_SET != tchild )
210  return false;
211 
212  std::list< X3DNODE* >::iterator sR = m_Refs.begin();
213  std::list< X3DNODE* >::iterator eR = m_Refs.end();
214 
215  while( sR != eR )
216  {
217  if( *sR == aNode )
218  return false;
219 
220  ++sR;
221  }
222 
223  if( X3D_APPEARANCE == tchild )
224  {
225  if( NULL == appearance )
226  {
227  m_Refs.push_back( aNode );
228  aNode->addNodeRef( this );
229  appearance = aNode;
230  }
231  else
232  return false;
233  }
234  else
235  {
236  if( NULL == geometry )
237  {
238  m_Refs.push_back( aNode );
239  aNode->addNodeRef( this );
240  geometry = aNode;
241  }
242  else
243  return false;
244  }
245 
246  return true;
247 }
248 
249 
251 {
252  if( NULL == geometry || NULL == appearance )
253  return NULL;
254 
255  #if defined( DEBUG_X3D ) && ( DEBUG_X3D > 2 )
256  do {
257  std::ostringstream ostr;
258  ostr << " * [INFO] Translating Shape with " << m_Children.size();
259  ostr << " children, " << m_Refs.size() << " references and ";
260  ostr << m_BackPointers.size() << " backpointers";
261  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
262  } while( 0 );
263  #endif
264 
265  S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
266 
267  if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
268  {
269  #ifdef DEBUG_X3D
270  do {
271  std::ostringstream ostr;
272  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
273  ostr << " * [BUG] Shape does not have a Transform parent (parent ID: ";
274  ostr << ptype << ")";
275  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
276  } while( 0 );
277  #endif
278 
279  return NULL;
280  }
281 
282  if( m_sgNode )
283  {
284  if( NULL != aParent )
285  {
287  && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
288  {
289  return NULL;
290  }
291  else if( aParent != S3D::GetSGNodeParent( m_sgNode )
292  && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
293  {
294  return NULL;
295  }
296  }
297 
298  return m_sgNode;
299  }
300 
301  IFSG_SHAPE shNode( aParent );
302 
303  SGNODE* pShape = shNode.GetRawPtr();
304  SGNODE* pGeom = geometry->TranslateToSG( pShape );
305  SGNODE* pApp = appearance->TranslateToSG( pShape );
306 
307  if( NULL == pApp || NULL == pGeom )
308  {
309  if( pGeom )
310  {
311  IFSG_FACESET tmp( false );
312  tmp.Attach( pGeom );
313  tmp.Destroy();
314  }
315 
316  if( pApp )
317  {
318  IFSG_APPEARANCE tmp( false );
319  tmp.Attach( pApp );
320  tmp.Destroy();
321  }
322 
323  shNode.Destroy();
324  return NULL;
325  }
326 
327  m_sgNode = shNode.GetRawPtr();
328 
329  return m_sgNode;
330 }
331 
332 
333 void X3DSHAPE::unlinkChildNode( const X3DNODE* aNode )
334 {
335  if( NULL == aNode )
336  return;
337 
338  if( aNode == appearance )
339  appearance = NULL;
340  else if( aNode == geometry )
341  geometry = NULL;
342 
343  X3DNODE::unlinkChildNode( aNode );
344  return;
345 }
346 
347 
348 void X3DSHAPE::unlinkRefNode( const X3DNODE* aNode )
349 {
350  if( NULL == aNode )
351  return;
352 
353  if( aNode == appearance )
354  appearance = NULL;
355  else if( aNode == geometry )
356  geometry = NULL;
357 
358  X3DNODE::unlinkRefNode( aNode );
359  return;
360 }
bool AddRefNode(X3DNODE *aNode) override
Definition: x3d_shape.cpp:202
virtual bool SetParent(X3DNODE *aParent, bool doUnlink=true)=0
Function SetParent sets the parent X3DNODE of this object.
bool ReadIndexedFaceSet(wxXmlNode *aNode, X3DNODE *aParent, X3D_DICT &aDict)
Definition: x3d_ops.cpp:160
std::list< X3DNODE * > m_BackPointers
Definition: x3d_base.h:82
bool Attach(SGNODE *aNode) override
Function Attach associates a given SGNODE* with this wrapper.
#define MASK_VRML
Definition: wrltypes.h:37
SGNODE * TranslateToSG(SGNODE *aParent) override
Function TranslateToSG produces a representation of the data using the intermediate scenegraph struct...
Definition: x3d_shape.cpp:250
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
X3DNODE * appearance
Definition: x3d_shape.h:44
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:636
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 Attach(SGNODE *aNode) override
Function Attach associates a given SGNODE* with this wrapper.
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:645
std::list< X3DNODE * > m_Children
Definition: x3d_base.h:83
X3DNODE represents the base class of all X3D nodes.
Definition: x3d_base.h:75
virtual void unlinkRefNode(const X3DNODE *aNode)
Function unlinkRef removes pointers to a referenced node; it is invoked by the referenced node upon d...
Definition: x3d_base.cpp:121
#define NULL
bool SetParent(X3DNODE *aParent, bool doUnlink=true) override
Function SetParent sets the parent X3DNODE of this object.
Definition: x3d_shape.cpp:128
bool ReadAppearance(wxXmlNode *aNode, X3DNODE *aParent, X3D_DICT &aDict)
Definition: x3d_ops.cpp:120
virtual SGNODE * TranslateToSG(SGNODE *aParent)=0
Function TranslateToSG produces a representation of the data using the intermediate scenegraph struct...
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:654
bool Read(wxXmlNode *aNode, X3DNODE *aTopNode, X3D_DICT &aDict) override
Definition: x3d_shape.cpp:81
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
bool AddName(const wxString &aName, X3DNODE *aNode)
Definition: x3d_base.cpp:34
SGTYPES
Definition: sg_types.h:34
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:59
IFSG_FACESET is the wrapper for the SGFACESET class.
Definition: ifsg_faceset.h:40
bool AddChildNode(X3DNODE *aNode) override
Definition: x3d_shape.cpp:153
void Destroy(void)
Function Destroy deletes the object held by this wrapper.
Definition: ifsg_node.cpp:54
X3DNODES
Definition: x3d_base.h:59
X3D_DICT * m_Dict
Definition: x3d_base.h:80
virtual void unlinkChildNode(const X3DNODE *aNode) override
Function unlinkChild removes references to an owned child; it is invoked by the child upon destructio...
Definition: x3d_shape.cpp:333
virtual ~X3DSHAPE()
Definition: x3d_shape.cpp:65
virtual void unlinkRefNode(const X3DNODE *aNode) override
Function unlinkRef removes pointers to a referenced node; it is invoked by the referenced node upon d...
Definition: x3d_shape.cpp:348
X3DNODE * geometry
Definition: x3d_shape.h:45
IFSG_SHAPE is the wrapper for the SGSHAPE class.
Definition: ifsg_shape.h:40
std::list< X3DNODE * > m_Refs
Definition: x3d_base.h:84