KiCad PCB EDA Suite
sg_index.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-2017 Cirilo Bernardo <[email protected]>
5  * Copyright (C) 2020 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, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <iostream>
26 #include <sstream>
27 #include <wx/log.h>
28 
29 #include "3d_cache/sg/sg_index.h"
30 
31 
32 SGINDEX::SGINDEX( SGNODE* aParent ) : SGNODE( aParent )
33 {
34  if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
35  {
36  m_Parent = nullptr;
37 
38  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGINDEX (type "
39  "'%d')" ),
40  __FILE__, __FUNCTION__, __LINE__,
41  aParent->GetNodeType() );
42  }
43 }
44 
45 
47 {
48  index.clear();
49 }
50 
51 
52 bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
53 {
54  if( nullptr != m_Parent )
55  {
56  if( aParent == m_Parent )
57  return true;
58 
59  // handle the change in parents
60  if( notify )
61  m_Parent->unlinkChildNode( this );
62 
63  m_Parent = nullptr;
64 
65  if( nullptr == aParent )
66  return true;
67  }
68 
69  // only a SGFACESET may be parent to a SGINDEX and derived types
70  if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
71  return false;
72 
73  m_Parent = aParent;
74 
75  if( m_Parent )
76  m_Parent->AddChildNode( this );
77 
78  return true;
79 }
80 
81 
82 SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept
83 {
84  if( nullptr == aNodeName || 0 == aNodeName[0] )
85  return nullptr;
86 
87  if( !m_Name.compare( aNodeName ) )
88  return this;
89 
90  return nullptr;
91 }
92 
93 
94 void SGINDEX::unlinkChildNode( const SGNODE* aCaller ) noexcept
95 {
96  // Node should have no children or refs.
97  wxCHECK( false, /* void */ );
98 }
99 
100 
101 void SGINDEX::unlinkRefNode( const SGNODE* aCaller ) noexcept
102 {
103  // Node should have no children or refs.
104  wxCHECK( false, /* void */ );
105 }
106 
107 
108 bool SGINDEX::AddRefNode( SGNODE* aNode ) noexcept
109 {
110  // Node should have no children or refs.
111  wxCHECK( false, false );
112 
113  return false;
114 }
115 
116 
117 bool SGINDEX::AddChildNode( SGNODE* aNode ) noexcept
118 {
119  // Node should have no children or refs.
120  wxCHECK( false, false );
121 
122  return false;
123 }
124 
125 
126 bool SGINDEX::GetIndices( size_t& nIndices, int*& aIndexList )
127 {
128  if( index.empty() )
129  {
130  nIndices = 0;
131  aIndexList = nullptr;
132  return false;
133  }
134 
135  nIndices = index.size();
136  aIndexList = & index[0];
137  return true;
138 }
139 
140 
141 void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
142 {
143  index.clear();
144 
145  if( 0 == nIndices || nullptr == aIndexList )
146  return;
147 
148  for( size_t i = 0; i < nIndices; ++i )
149  index.push_back( aIndexList[i] );
150 
151  return;
152 }
153 
154 
155 void SGINDEX::AddIndex( int aIndex )
156 {
157  index.push_back( aIndex );
158 }
159 
160 
162 {
163  m_written = false;
164 
165  // rename this node
166  m_Name.clear();
167  GetName();
168 }
169 
170 
171 bool SGINDEX::WriteVRML( std::ostream& aFile, bool aReuseFlag )
172 {
173  if( index.empty() )
174  return false;
175 
177  return writeCoordIndex( aFile );
178 
179  return writeColorIndex( aFile );
180 }
181 
182 
183 bool SGINDEX::writeCoordIndex( std::ostream& aFile )
184 {
185  size_t n = index.size();
186 
187  wxCHECK_MSG( n % 3 == 0, false, wxT( "Coordinate index is not divisible by three (violates "
188  "triangle constraint)" ) );
189 
190  aFile << " coordIndex [\n ";
191 
192  // indices to control formatting
193  int nv0 = 0;
194  int nv1 = 0;
195 
196  for( size_t i = 0; i < n; )
197  {
198  aFile << index[i];
199  ++i;
200 
201  if( ++nv0 == 3 )
202  {
203  aFile << ",-1";
204  ++nv1;
205  nv0 = 0;
206  }
207 
208  if( i < n )
209  {
210  aFile << ",";
211 
212  if( nv1 == 8 )
213  {
214  nv1 = 0;
215  aFile << "\n ";
216  }
217  }
218  }
219 
220  aFile << "]\n";
221 
222  return true;
223 }
224 
225 
226 bool SGINDEX::writeColorIndex( std::ostream& aFile )
227 {
228  aFile << " colorIndex [\n ";
229  return writeIndexList( aFile );
230 }
231 
232 
233 bool SGINDEX::writeIndexList( std::ostream& aFile )
234 {
235  // index to control formatting
236  int nv = 0;
237  size_t n = index.size();
238 
239  for( size_t i = 0; i < n; )
240  {
241  aFile << index[i];
242  ++i;
243 
244  if( i < n )
245  {
246  aFile << ",";
247 
248  if( ++nv == 20 )
249  {
250  aFile << "\n ";
251  nv = 0;
252  }
253  }
254  }
255 
256  aFile << "]\n";
257 
258  return true;
259 }
260 
261 
262 bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
263 {
264  if( nullptr == parentNode )
265  {
266  wxCHECK( m_Parent, false );
267 
268  SGNODE* np = m_Parent;
269 
270  while( nullptr != np->GetParent() )
271  np = np->GetParent();
272 
273  if( np->WriteCache( aFile, nullptr ) )
274  {
275  m_written = true;
276  return true;
277  }
278 
279  return false;
280  }
281 
282  wxCHECK( parentNode == m_Parent, false );
283 
284  if( !aFile.good() )
285  {
286  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
287  __FILE__, __FUNCTION__, __LINE__ );
288 
289  return false;
290  }
291 
292  aFile << "[" << GetName() << "]";
293  size_t npts = index.size();
294  aFile.write( (char*)&npts, sizeof(size_t) );
295 
296  for( size_t i = 0; i < npts; ++i )
297  aFile.write( (char*)&index[i], sizeof(int) );
298 
299  if( aFile.fail() )
300  return false;
301 
302  m_written = true;
303  return true;
304 }
305 
306 
307 bool SGINDEX::ReadCache( std::istream& aFile, SGNODE* parentNode )
308 {
309  wxCHECK( index.empty(), false );
310 
311  size_t npts;
312  aFile.read( (char*)&npts, sizeof(size_t) );
313  int tmp;
314 
315  if( aFile.fail() )
316  return false;
317 
318  for( size_t i = 0; i < npts; ++i )
319  {
320  aFile.read( (char*) &tmp, sizeof( int ) );
321 
322  if( aFile.fail() )
323  return false;
324 
325  index.push_back( tmp );
326  }
327 
328  return true;
329 }
SGINDEX(SGNODE *aParent)
Definition: sg_index.cpp:32
SGNODE * m_Parent
Pointer to parent node; may be NULL for top level transform.
Definition: sg_node.h:227
bool AddRefNode(SGNODE *aNode) noexcept override
Definition: sg_index.cpp:108
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Set the parent SGNODE of this object.
Definition: sg_index.cpp:52
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Writes this node's data to a VRML file.
Definition: sg_index.cpp:171
bool writeColorIndex(std::ostream &aFile)
Definition: sg_index.cpp:226
void unlinkChildNode(const SGNODE *aCaller) noexcept override
Remove references to an owned child.
Definition: sg_index.cpp:94
std::vector< int > index
Definition: sg_index.h:95
The base class of all Scene Graph nodes.
Definition: sg_node.h:74
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Write this node's data to a binary cache file.
Definition: sg_index.cpp:262
void ReNameNodes(void) override
Rename a node and all its child nodes in preparation for write operations.
Definition: sg_index.cpp:161
const char * GetName(void)
Definition: sg_node.cpp:146
void unlinkRefNode(const SGNODE *aCaller) noexcept override
Remove pointers to a referenced node.
Definition: sg_index.cpp:101
bool m_written
Set to true when the object has been written after a ReNameNodes().
Definition: sg_node.h:230
bool writeCoordIndex(std::ostream &aFile)
Definition: sg_index.cpp:183
virtual void unlinkChildNode(const SGNODE *aNode)=0
Remove references to an owned child.
bool GetIndices(size_t &nIndices, int *&aIndexList)
Retrieve the number of indices and a pointer to the list.
Definition: sg_index.cpp:126
virtual ~SGINDEX()
Definition: sg_index.cpp:46
bool writeIndexList(std::ostream &aFile)
Definition: sg_index.cpp:233
bool AddChildNode(SGNODE *aNode) noexcept override
Definition: sg_index.cpp:117
SGNODE * GetParent(void) const noexcept
Returns a pointer to the parent SGNODE of this object or NULL if the object has no parent (ie.
Definition: sg_node.cpp:110
std::string m_Name
name to use for referencing the entity by name.
Definition: sg_node.h:229
virtual bool WriteCache(std::ostream &aFile, SGNODE *parentNode)=0
Write this node's data to a binary cache file.
S3D::SGTYPES m_SGtype
Type of Scene Graph node.
Definition: sg_node.h:228
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Reads binary format data from a cache file.
Definition: sg_index.cpp:307
void SetIndices(size_t nIndices, int *aIndexList)
Set the number of indices and creates a copy of the given index data.
Definition: sg_index.cpp:141
virtual bool AddChildNode(SGNODE *aNode)=0
SGNODE * FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override
Search the tree of linked nodes and return a reference to the first node found with the given name.
Definition: sg_index.cpp:82
void AddIndex(int aIndex)
Add a single index to the list.
Definition: sg_index.cpp:155
S3D::SGTYPES GetNodeType(void) const noexcept
Return the type of this node instance.
Definition: sg_node.cpp:104