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 <cirilo.bernardo@gmail.com>
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, "%s:%s:%d * [BUG] inappropriate parent to SGINDEX (type '%d')",
39  __FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
40  }
41 }
42 
43 
45 {
46  index.clear();
47 }
48 
49 
50 bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
51 {
52  if( nullptr != m_Parent )
53  {
54  if( aParent == m_Parent )
55  return true;
56 
57  // handle the change in parents
58  if( notify )
59  m_Parent->unlinkChildNode( this );
60 
61  m_Parent = nullptr;
62 
63  if( nullptr == aParent )
64  return true;
65  }
66 
67  // only a SGFACESET may be parent to a SGINDEX and derived types
68  if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
69  return false;
70 
71  m_Parent = aParent;
72 
73  if( m_Parent )
74  m_Parent->AddChildNode( this );
75 
76  return true;
77 }
78 
79 
80 SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept
81 {
82  if( nullptr == aNodeName || 0 == aNodeName[0] )
83  return nullptr;
84 
85  if( !m_Name.compare( aNodeName ) )
86  return this;
87 
88  return nullptr;
89 }
90 
91 
92 void SGINDEX::unlinkChildNode( const SGNODE* aCaller ) noexcept
93 {
94  // Node should have no children or refs.
95  wxCHECK( false, /* void */ );
96 }
97 
98 
99 void SGINDEX::unlinkRefNode( const SGNODE* aCaller ) noexcept
100 {
101  // Node should have no children or refs.
102  wxCHECK( false, /* void */ );
103 }
104 
105 
106 bool SGINDEX::AddRefNode( SGNODE* aNode ) noexcept
107 {
108  // Node should have no children or refs.
109  wxCHECK( false, false );
110 
111  return false;
112 }
113 
114 
115 bool SGINDEX::AddChildNode( SGNODE* aNode ) noexcept
116 {
117  // Node should have no children or refs.
118  wxCHECK( false, false );
119 
120  return false;
121 }
122 
123 
124 bool SGINDEX::GetIndices( size_t& nIndices, int*& aIndexList )
125 {
126  if( index.empty() )
127  {
128  nIndices = 0;
129  aIndexList = nullptr;
130  return false;
131  }
132 
133  nIndices = index.size();
134  aIndexList = & index[0];
135  return true;
136 }
137 
138 
139 void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
140 {
141  index.clear();
142 
143  if( 0 == nIndices || nullptr == aIndexList )
144  return;
145 
146  for( size_t i = 0; i < nIndices; ++i )
147  index.push_back( aIndexList[i] );
148 
149  return;
150 }
151 
152 
153 void SGINDEX::AddIndex( int aIndex )
154 {
155  index.push_back( aIndex );
156 }
157 
158 
160 {
161  m_written = false;
162 
163  // rename this node
164  m_Name.clear();
165  GetName();
166 }
167 
168 
169 bool SGINDEX::WriteVRML( std::ostream& aFile, bool aReuseFlag )
170 {
171  if( index.empty() )
172  return false;
173 
175  return writeCoordIndex( aFile );
176 
177  return writeColorIndex( aFile );
178 }
179 
180 
181 bool SGINDEX::writeCoordIndex( std::ostream& aFile )
182 {
183  size_t n = index.size();
184 
185  wxCHECK_MSG( n % 3 == 0, false,
186  "Coordinate index is not divisible by three (violates triangle constraint)" );
187 
188  aFile << " coordIndex [\n ";
189 
190  // indices to control formatting
191  int nv0 = 0;
192  int nv1 = 0;
193 
194  for( size_t i = 0; i < n; )
195  {
196  aFile << index[i];
197  ++i;
198 
199  if( ++nv0 == 3 )
200  {
201  aFile << ",-1";
202  ++nv1;
203  nv0 = 0;
204  }
205 
206  if( i < n )
207  {
208  aFile << ",";
209 
210  if( nv1 == 8 )
211  {
212  nv1 = 0;
213  aFile << "\n ";
214  }
215  }
216  }
217 
218  aFile << "]\n";
219 
220  return true;
221 }
222 
223 
224 bool SGINDEX::writeColorIndex( std::ostream& aFile )
225 {
226  aFile << " colorIndex [\n ";
227  return writeIndexList( aFile );
228 }
229 
230 
231 bool SGINDEX::writeIndexList( std::ostream& aFile )
232 {
233  // index to control formatting
234  int nv = 0;
235  size_t n = index.size();
236 
237  for( size_t i = 0; i < n; )
238  {
239  aFile << index[i];
240  ++i;
241 
242  if( i < n )
243  {
244  aFile << ",";
245 
246  if( ++nv == 20 )
247  {
248  aFile << "\n ";
249  nv = 0;
250  }
251  }
252  }
253 
254  aFile << "]\n";
255 
256  return true;
257 }
258 
259 
260 bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
261 {
262  if( nullptr == parentNode )
263  {
264  wxCHECK( m_Parent, false );
265 
266  SGNODE* np = m_Parent;
267 
268  while( nullptr != np->GetParent() )
269  np = np->GetParent();
270 
271  if( np->WriteCache( aFile, nullptr ) )
272  {
273  m_written = true;
274  return true;
275  }
276 
277  return false;
278  }
279 
280  wxCHECK( parentNode == m_Parent, false );
281 
282  if( !aFile.good() )
283  {
284  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] bad stream",
285  __FILE__, __FUNCTION__, __LINE__ );
286 
287  return false;
288  }
289 
290  aFile << "[" << GetName() << "]";
291  size_t npts = index.size();
292  aFile.write( (char*)&npts, sizeof(size_t) );
293 
294  for( size_t i = 0; i < npts; ++i )
295  aFile.write( (char*)&index[i], sizeof(int) );
296 
297  if( aFile.fail() )
298  return false;
299 
300  m_written = true;
301  return true;
302 }
303 
304 
305 bool SGINDEX::ReadCache( std::istream& aFile, SGNODE* parentNode )
306 {
307  wxCHECK( index.empty(), false );
308 
309  size_t npts;
310  aFile.read( (char*)&npts, sizeof(size_t) );
311  int tmp;
312 
313  if( aFile.fail() )
314  return false;
315 
316  for( size_t i = 0; i < npts; ++i )
317  {
318  aFile.read( (char*) &tmp, sizeof( int ) );
319 
320  if( aFile.fail() )
321  return false;
322 
323  index.push_back( tmp );
324  }
325 
326  return true;
327 }
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:106
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Set the parent SGNODE of this object.
Definition: sg_index.cpp:50
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Writes this node's data to a VRML file.
Definition: sg_index.cpp:169
bool writeColorIndex(std::ostream &aFile)
Definition: sg_index.cpp:224
void unlinkChildNode(const SGNODE *aCaller) noexcept override
Remove references to an owned child.
Definition: sg_index.cpp:92
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:260
void ReNameNodes(void) override
Rename a node and all its child nodes in preparation for write operations.
Definition: sg_index.cpp:159
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:99
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:181
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:124
virtual ~SGINDEX()
Definition: sg_index.cpp:44
bool writeIndexList(std::ostream &aFile)
Definition: sg_index.cpp:231
bool AddChildNode(SGNODE *aNode) noexcept override
Definition: sg_index.cpp:115
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:305
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:139
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:80
void AddIndex(int aIndex)
Add a single index to the list.
Definition: sg_index.cpp:153
S3D::SGTYPES GetNodeType(void) const noexcept
Return the type of this node instance.
Definition: sg_node.cpp:104