KiCad PCB EDA Suite
Loading...
Searching...
No Matches
vrml2_node.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 <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21
22#include <set>
23#include <map>
24#include <utility>
25#include <iterator>
26#include <cctype>
27#include <iostream>
28#include <sstream>
29#include <algorithm>
30#include <wx/log.h>
31
32#include "vrml2_node.h"
33
34
35static std::set< std::string > badNames;
36
37typedef std::pair< std::string, WRL2NODES > NODEITEM;
38typedef std::map< std::string, WRL2NODES > NODEMAP;
40
41
43{
44 m_sgNode = nullptr;
45 m_Parent = nullptr;
47
48 if( badNames.empty() )
49 {
50 badNames.emplace( "DEF" );
51 badNames.emplace( "EXTERNPROTO" );
52 badNames.emplace( "FALSE" );
53 badNames.emplace( "IS" );
54 badNames.emplace( "NULL" );
55 badNames.emplace( "PROTO" );
56 badNames.emplace( "ROUTE" );
57 badNames.emplace( "TO" );
58 badNames.emplace( "TRUE" );
59 badNames.emplace( "USE" );
60 badNames.emplace( "eventIn" );
61 badNames.emplace( "eventOut" );
62 badNames.emplace( "exposedField" );
63 badNames.emplace( "field" );
64 }
65
66 if( nodenames.empty() )
67 {
68 nodenames.emplace( NODEITEM( "Anchor", WRL2NODES::WRL2_ANCHOR ) );
69 nodenames.emplace( NODEITEM( "Appearance", WRL2NODES::WRL2_APPEARANCE ) );
70 nodenames.emplace( NODEITEM( "Audioclip", WRL2NODES::WRL2_AUDIOCLIP ) );
71 nodenames.emplace( NODEITEM( "Background", WRL2NODES::WRL2_BACKGROUND ) );
72 nodenames.emplace( NODEITEM( "Billboard", WRL2NODES::WRL2_BILLBOARD ) );
73 nodenames.emplace( NODEITEM( "Box", WRL2NODES::WRL2_BOX ) );
74 nodenames.emplace( NODEITEM( "Collision", WRL2NODES::WRL2_COLLISION ) );
75 nodenames.emplace( NODEITEM( "Color", WRL2NODES::WRL2_COLOR ) );
76 nodenames.emplace( NODEITEM( "ColorInterpolator", WRL2NODES::WRL2_COLORINTERPOLATOR ) );
77 nodenames.emplace( NODEITEM( "Cone", WRL2NODES::WRL2_CONE ) );
78 nodenames.emplace( NODEITEM( "Coordinate", WRL2NODES::WRL2_COORDINATE ) );
79 nodenames.emplace( NODEITEM( "CoordinateInterpolator",
81 nodenames.emplace( NODEITEM( "Cylinder", WRL2NODES::WRL2_CYLINDER ) );
82 nodenames.emplace( NODEITEM( "CylinderSensor", WRL2NODES::WRL2_CYLINDERSENSOR ) );
83 nodenames.emplace( NODEITEM( "DirectionalLight", WRL2NODES::WRL2_DIRECTIONALLIGHT ) );
84 nodenames.emplace( NODEITEM( "ElevationGrid", WRL2NODES::WRL2_ELEVATIONGRID ) );
85 nodenames.emplace( NODEITEM( "Extrusion", WRL2NODES::WRL2_EXTRUSION ) );
86 nodenames.emplace( NODEITEM( "Fog", WRL2NODES::WRL2_FOG ) );
87 nodenames.emplace( NODEITEM( "FontStyle", WRL2NODES::WRL2_FONTSTYLE ) );
88 nodenames.emplace( NODEITEM( "Group", WRL2NODES::WRL2_GROUP ) );
89 nodenames.emplace( NODEITEM( "ImageTexture", WRL2NODES::WRL2_IMAGETEXTURE ) );
90 nodenames.emplace( NODEITEM( "IndexedFaceSet", WRL2NODES::WRL2_INDEXEDFACESET ) );
91 nodenames.emplace( NODEITEM( "IndexedLineSet", WRL2NODES::WRL2_INDEXEDLINESET ) );
92 nodenames.emplace( NODEITEM( "Inline", WRL2NODES::WRL2_INLINE ) );
93 nodenames.emplace( NODEITEM( "LOD", WRL2NODES::WRL2_LOD ) );
94 nodenames.emplace( NODEITEM( "Material", WRL2NODES::WRL2_MATERIAL ) );
95 nodenames.emplace( NODEITEM( "MovieTexture", WRL2NODES::WRL2_MOVIETEXTURE ) );
96 nodenames.emplace( NODEITEM( "NavigationInfo", WRL2NODES::WRL2_NAVIGATIONINFO ) );
97 nodenames.emplace( NODEITEM( "Normal", WRL2NODES::WRL2_NORMAL ) );
98 nodenames.emplace( NODEITEM( "NormalInterpolator", WRL2NODES::WRL2_NORMALINTERPOLATOR ) );
99 nodenames.emplace( NODEITEM( "OrientationInterpolator",
101 nodenames.emplace( NODEITEM( "PixelTexture", WRL2NODES::WRL2_PIXELTEXTURE ) );
102 nodenames.emplace( NODEITEM( "PlaneSensor", WRL2NODES::WRL2_PLANESENSOR ) );
103 nodenames.emplace( NODEITEM( "PointLight", WRL2NODES::WRL2_POINTLIGHT ) );
104 nodenames.emplace( NODEITEM( "PointSet", WRL2NODES::WRL2_POINTSET ) );
105 nodenames.emplace( NODEITEM( "PositionInterpolator",
107 nodenames.emplace( NODEITEM( "ProximitySensor", WRL2NODES::WRL2_PROXIMITYSENSOR ) );
108 nodenames.emplace( NODEITEM( "ScalarInterpolator", WRL2NODES::WRL2_SCALARINTERPOLATOR ) );
109 nodenames.emplace( NODEITEM( "Script", WRL2NODES::WRL2_SCRIPT ) );
110 nodenames.emplace( NODEITEM( "Shape", WRL2NODES::WRL2_SHAPE ) );
111 nodenames.emplace( NODEITEM( "Sound", WRL2NODES::WRL2_SOUND ) );
112 nodenames.emplace( NODEITEM( "Sphere", WRL2NODES::WRL2_SPHERE ) );
113 nodenames.emplace( NODEITEM( "SphereSensor", WRL2NODES::WRL2_SPHERESENSOR ) );
114 nodenames.emplace( NODEITEM( "SpotLight", WRL2NODES::WRL2_SPOTLIGHT ) );
115 nodenames.emplace( NODEITEM( "Switch", WRL2NODES::WRL2_SWITCH ) );
116 nodenames.emplace( NODEITEM( "Text", WRL2NODES::WRL2_TEXT ) );
117 nodenames.emplace( NODEITEM( "TextureCoordinate", WRL2NODES::WRL2_TEXTURECOORDINATE ) );
118 nodenames.emplace( NODEITEM( "TextureTransform", WRL2NODES::WRL2_TEXTURETRANSFORM ) );
119 nodenames.emplace( NODEITEM( "TimeSensor", WRL2NODES::WRL2_TIMESENSOR ) );
120 nodenames.emplace( NODEITEM( "TouchSensor", WRL2NODES::WRL2_TOUCHSENSOR ) );
121 nodenames.emplace( NODEITEM( "Transform", WRL2NODES::WRL2_TRANSFORM ) );
122 nodenames.emplace( NODEITEM( "ViewPoint", WRL2NODES::WRL2_VIEWPOINT ) );
123 nodenames.emplace( NODEITEM( "VisibilitySensor", WRL2NODES::WRL2_VISIBILITYSENSOR ) );
124 nodenames.emplace( NODEITEM( "WorldInfo", WRL2NODES::WRL2_WORLDINFO ) );
125 }
126}
127
128
130{
131 if( m_Parent )
132 m_Parent->unlinkChildNode( this );
133
134 std::list< WRL2NODE* >::iterator sBP = m_BackPointers.begin();
135 std::list< WRL2NODE* >::iterator eBP = m_BackPointers.end();
136
137 while( sBP != eBP )
138 {
139 (*sBP)->unlinkRefNode( this );
140 ++sBP;
141 }
142
143 std::list< WRL2NODE* >::iterator sC = m_Refs.begin();
144 std::list< WRL2NODE* >::iterator eC = m_Refs.end();
145
146 while( sC != eC )
147 {
148 (*sC)->delNodeRef( this );
149 ++sC;
150 }
151
152 m_Refs.clear();
153 sC = m_Children.begin();
154 eC = m_Children.end();
155
156 while( sC != eC )
157 {
158 (*sC)->SetParent( nullptr, false );
159 delete *sC;
160 ++sC;
161 }
162
163 m_Children.clear();
164}
165
166
168{
169 // the parent node must never be added as a backpointer
170 if( aNode == m_Parent )
171 return;
172
173 std::list< WRL2NODE* >::iterator np =
174 std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
175
176 if( np != m_BackPointers.end() )
177 return;
178
179 m_BackPointers.push_back( aNode );
180}
181
182
184{
185 std::list< WRL2NODE* >::iterator np =
186 std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
187
188 if( np != m_BackPointers.end() )
189 {
190 m_BackPointers.erase( np );
191 return;
192 }
193
194 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
195 " * [BUG] delNodeRef() did not find its target." ),
196 __FILE__, __FUNCTION__, __LINE__ );
197}
198
199
201{
202 return m_Type;
203}
204
205
207{
208 return m_Parent;
209}
210
211
212std::string WRL2NODE::GetName( void )
213{
214 return m_Name;
215}
216
217
218bool WRL2NODE::SetName( const std::string& aName )
219{
220 if( aName.empty() )
221 return false;
222
223 std::set< std::string >::iterator item = badNames.find( aName );
224
225 if( item != badNames.end() )
226 {
227 wxLogTrace( traceVrmlPlugin,
228 wxT( "%s:%s:%d\n"
229 " * [INFO] invalid node name '%s' (matches restricted word)" ),
230 __FILE__, __FUNCTION__, __LINE__, *item );
231
232 return false;
233 }
234
235
236 if( isdigit( aName[0] ) )
237 {
238 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
239 " * [INFO] invalid node name '%s' (begins with digit)" ),
240 __FILE__, __FUNCTION__, __LINE__, aName );
241
242 return false;
243 }
244
245 // The characters '+' and '-' are not allowed in names as per the VRML2 specification;
246 // however many parsers accept them and many bad generators use them so the rules
247 // have been relaxed here.
248 // #define BAD_CHARS1 "\"\'#+,-.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F"
249 #define BAD_CHARS1 "\"\'#,.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F"
250 #define BAD_CHARS2 "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
251
252 if( std::string::npos != aName.find_first_of( BAD_CHARS1 )
253 || std::string::npos != aName.find_first_of( BAD_CHARS2 ) )
254 {
255 wxLogTrace( traceVrmlPlugin,
256 wxT( "%s:%s:%d\n"
257 " * [INFO] invalid node name '%s' (contains invalid character)" ),
258 __FILE__, __FUNCTION__, __LINE__, aName );
259
260 return false;
261 }
262
263 m_Name = aName;
264
265 return true;
266}
267
268
269const char* WRL2NODE::GetNodeTypeName( WRL2NODES aNodeType ) const
270{
271 if( aNodeType < WRL2NODES::WRL2_BASE || aNodeType >= WRL2NODES::WRL2_END )
272 return "*INVALID_TYPE*";
273
274 if( aNodeType == WRL2NODES::WRL2_BASE )
275 return "*VIRTUAL_BASE*";
276
277 NODEMAP::iterator it = nodenames.begin();
278 advance( it, (static_cast<int>( aNodeType ) - static_cast<int>( WRL2NODES::WRL2_BEGIN ) ) );
279
280 return it->first.c_str();
281}
282
283
284WRL2NODES WRL2NODE::getNodeTypeID( const std::string& aNodeName )
285{
286 NODEMAP::iterator it = nodenames.find( aNodeName );
287
288 if( nodenames.end() != it )
289 return it->second;
290
292}
293
294
295std::string WRL2NODE::GetError( void )
296{
297 return m_error;
298}
299
300
301WRL2NODE* WRL2NODE::FindNode( const std::string& aNodeName, const WRL2NODE *aCaller )
302{
303 if( aNodeName.empty() )
304 return nullptr;
305
306 if( !m_Name.compare( aNodeName ) )
307 return this;
308
309 std::list< WRL2NODE* >::iterator sLA = m_Children.begin();
310 std::list< WRL2NODE* >::iterator eLA = m_Children.end();
311
312 WRL2NODE* psg = nullptr;
313
314 while( sLA != eLA )
315 {
316 if( *sLA != aCaller )
317 {
318 psg = (*sLA)->FindNode( aNodeName, this );
319
320 if( nullptr != psg )
321 return psg;
322
323 }
324
325 ++sLA;
326 }
327
328 if( nullptr != m_Parent && aCaller != m_Parent )
329 return m_Parent->FindNode( aNodeName, this );
330
331 return nullptr;
332}
333
334
335bool WRL2NODE::SetParent( WRL2NODE* aParent, bool doUnlink )
336{
337 if( aParent == m_Parent )
338 return true;
339
340 if( nullptr != m_Parent && doUnlink )
341 m_Parent->unlinkChildNode( this );
342
343 m_Parent = aParent;
344
345 if( nullptr != m_Parent )
346 m_Parent->AddChildNode( this );
347
348 return true;
349}
350
351
353{
354 wxCHECK_MSG( aNode, false, wxT( "Invalid node pointer." ) );
355 wxCHECK_MSG( aNode->GetNodeType() != WRL2NODES::WRL2_BASE, false,
356 wxT( "Attempting to add a base node to another node." ) );
357
358
359 std::list< WRL2NODE* >::iterator sC = m_Children.begin();
360 std::list< WRL2NODE* >::iterator eC = m_Children.end();
361
362 while( sC != eC )
363 {
364 if( *sC == aNode )
365 return false;
366
367 ++sC;
368 }
369
370 m_Children.push_back( aNode );
371
372 if( aNode->GetParent() != this )
373 aNode->SetParent( this );
374
375 return true;
376}
377
378
380{
381 wxCHECK_MSG( aNode, false, wxT( "Invalid node pointer." ) );
382 wxCHECK_MSG( aNode->GetNodeType() != WRL2NODES::WRL2_BASE, false,
383 wxT( "Attempt to add a base node reference to another base node" ) );
384
385 std::list< WRL2NODE* >::iterator sR = m_Refs.begin();
386 std::list< WRL2NODE* >::iterator eR = m_Refs.end();
387
388 while( sR != eR )
389 {
390 if( *sR == aNode )
391 return true;
392
393 ++sR;
394 }
395
396 m_Refs.push_back( aNode );
397 aNode->addNodeRef( this );
398
399 return true;
400}
401
402
404{
405 std::list< WRL2NODE* >::iterator sL = m_Children.begin();
406 std::list< WRL2NODE* >::iterator eL = m_Children.end();
407
408 while( sL != eL )
409 {
410 if( *sL == aNode )
411 {
412 m_Children.erase( sL );
413 return;
414 }
415
416 ++sL;
417 }
418}
419
420
422{
423 std::list< WRL2NODE* >::iterator sL = m_Refs.begin();
424 std::list< WRL2NODE* >::iterator eL = m_Refs.end();
425
426 while( sL != eL )
427 {
428 if( *sL == aNode )
429 {
430 m_Refs.erase( sL );
431 return;
432 }
433
434 ++sL;
435 }
436}
void addNodeRef(WRL2NODE *aNode)
Add a pointer to a node which references but does not own this node.
virtual bool SetName(const std::string &aName)
SGNODE * m_sgNode
Definition vrml2_node.h:174
WRL2NODES getNodeTypeID(const std::string &aNodeName)
virtual ~WRL2NODE()
std::list< WRL2NODE * > m_BackPointers
Definition vrml2_node.h:169
WRL2NODE * GetParent(void) const
virtual std::string GetName(void)
virtual bool SetParent(WRL2NODE *aParent, bool doUnlink=true)
Set the parent WRL2NODE of this object.
virtual void unlinkChildNode(const WRL2NODE *aNode)
Remove references to an owned child.
std::string GetError(void)
WRL2NODE * m_Parent
Definition vrml2_node.h:165
std::string m_Name
Definition vrml2_node.h:167
std::list< WRL2NODE * > m_Children
Definition vrml2_node.h:170
virtual WRL2NODE * FindNode(const std::string &aNodeName, const WRL2NODE *aCaller)
Search the tree of linked nodes and returns a reference to the first node found with the given name.
WRL2NODES m_Type
Definition vrml2_node.h:166
virtual bool AddRefNode(WRL2NODE *aNode)
void delNodeRef(WRL2NODE *aNode)
Remove a pointer to a node which references but does not own this node.
virtual void unlinkRefNode(const WRL2NODE *aNode)
Remove pointers to a referenced node.
const char * GetNodeTypeName(WRL2NODES aNodeType) const
WRL2NODES GetNodeType(void) const
std::list< WRL2NODE * > m_Refs
Definition vrml2_node.h:171
virtual bool AddChildNode(WRL2NODE *aNode)
std::string m_error
Definition vrml2_node.h:172
const wxChar *const traceVrmlPlugin
Flag to enable VRML plugin trace output.
Definition vrml.cpp:59
std::map< std::string, std::vector< SGNODE * > > NODEMAP
Definition loadmodel.cpp:91
std::pair< std::string, std::vector< SGNODE * > > NODEITEM
Definition loadmodel.cpp:92
#define BAD_CHARS2
#define BAD_CHARS1
static NODEMAP nodenames
static std::set< std::string > badNames
WRL2NODES
Definition wrltypes.h:121
@ WRL2_CYLINDERSENSOR
Definition wrltypes.h:137
@ WRL2_TRANSFORM
Definition wrltypes.h:174
@ WRL2_POSITIONINTERPOLATOR
Definition wrltypes.h:159
@ WRL2_SPOTLIGHT
Definition wrltypes.h:167
@ WRL2_SCALARINTERPOLATOR
Definition wrltypes.h:161
@ WRL2_ORIENTATIONINTERPOLATOR
Definition wrltypes.h:154
@ WRL2_COLLISION
Definition wrltypes.h:130
@ WRL2_SPHERESENSOR
Definition wrltypes.h:166
@ WRL2_NAVIGATIONINFO
Definition wrltypes.h:151
@ WRL2_INDEXEDFACESET
Definition wrltypes.h:145
@ WRL2_INDEXEDLINESET
Definition wrltypes.h:146
@ WRL2_PLANESENSOR
Definition wrltypes.h:156
@ WRL2_INLINE
Definition wrltypes.h:147
@ WRL2_TOUCHSENSOR
Definition wrltypes.h:173
@ WRL2_MOVIETEXTURE
Definition wrltypes.h:150
@ WRL2_TIMESENSOR
Definition wrltypes.h:172
@ WRL2_DIRECTIONALLIGHT
Definition wrltypes.h:138
@ WRL2_BACKGROUND
Definition wrltypes.h:127
@ WRL2_COLORINTERPOLATOR
Definition wrltypes.h:132
@ WRL2_POINTLIGHT
Definition wrltypes.h:157
@ WRL2_PROXIMITYSENSOR
Definition wrltypes.h:160
@ WRL2_ELEVATIONGRID
Definition wrltypes.h:139
@ WRL2_TEXTURETRANSFORM
Definition wrltypes.h:171
@ WRL2_AUDIOCLIP
Definition wrltypes.h:126
@ WRL2_PIXELTEXTURE
Definition wrltypes.h:155
@ WRL2_BILLBOARD
Definition wrltypes.h:128
@ WRL2_COORDINATE
Definition wrltypes.h:134
@ WRL2_WORLDINFO
Definition wrltypes.h:177
@ WRL2_NORMALINTERPOLATOR
Definition wrltypes.h:153
@ WRL2_MATERIAL
Definition wrltypes.h:149
@ WRL2_NORMAL
Definition wrltypes.h:152
@ WRL2_COORDINATEINTERPOLATOR
Definition wrltypes.h:135
@ WRL2_FONTSTYLE
Definition wrltypes.h:142
@ WRL2_SWITCH
Definition wrltypes.h:168
@ WRL2_VIEWPOINT
Definition wrltypes.h:175
@ WRL2_IMAGETEXTURE
Definition wrltypes.h:144
@ WRL2_CYLINDER
Definition wrltypes.h:136
@ WRL2_SCRIPT
Definition wrltypes.h:162
@ WRL2_EXTRUSION
Definition wrltypes.h:140
@ WRL2_VISIBILITYSENSOR
Definition wrltypes.h:176
@ WRL2_INVALID
Definition wrltypes.h:178
@ WRL2_POINTSET
Definition wrltypes.h:158
@ WRL2_SPHERE
Definition wrltypes.h:165
@ WRL2_ANCHOR
Definition wrltypes.h:124
@ WRL2_APPEARANCE
Definition wrltypes.h:125
@ WRL2_TEXTURECOORDINATE
Definition wrltypes.h:170