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
30
31
32SGINDEX::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
52bool 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 )
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
82SGNODE* 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
94void SGINDEX::unlinkChildNode( const SGNODE* aCaller ) noexcept
95{
96 // Node should have no children or refs.
97 wxCHECK( false, /* void */ );
98}
99
100
101void SGINDEX::unlinkRefNode( const SGNODE* aCaller ) noexcept
102{
103 // Node should have no children or refs.
104 wxCHECK( false, /* void */ );
105}
106
107
108bool 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
117bool 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
126bool 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
141void 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
155void 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
171bool 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
183bool 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
226bool SGINDEX::writeColorIndex( std::ostream& aFile )
227{
228 aFile << " colorIndex [\n ";
229 return writeIndexList( aFile );
230}
231
232
233bool 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
262bool 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
307bool 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}
bool AddChildNode(SGNODE *aNode) noexcept override
Definition: sg_index.cpp:117
void unlinkChildNode(const SGNODE *aCaller) noexcept override
Remove references to an owned child.
Definition: sg_index.cpp:94
void unlinkRefNode(const SGNODE *aCaller) noexcept override
Remove pointers to a referenced node.
Definition: sg_index.cpp:101
SGINDEX(SGNODE *aParent)
Definition: sg_index.cpp:32
bool writeCoordIndex(std::ostream &aFile)
Definition: sg_index.cpp:183
bool GetIndices(size_t &nIndices, int *&aIndexList)
Retrieve the number of indices and a pointer to the list.
Definition: sg_index.cpp:126
std::vector< int > index
Definition: sg_index.h:95
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Writes this node's data to a VRML file.
Definition: sg_index.cpp:171
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Reads binary format data from a cache file.
Definition: sg_index.cpp:307
void AddIndex(int aIndex)
Add a single index to the list.
Definition: sg_index.cpp:155
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
bool writeColorIndex(std::ostream &aFile)
Definition: sg_index.cpp:226
void ReNameNodes(void) override
Rename a node and all its child nodes in preparation for write operations.
Definition: sg_index.cpp:161
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 ~SGINDEX()
Definition: sg_index.cpp:46
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Set the parent SGNODE of this object.
Definition: sg_index.cpp:52
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Write this node's data to a binary cache file.
Definition: sg_index.cpp:262
bool writeIndexList(std::ostream &aFile)
Definition: sg_index.cpp:233
bool AddRefNode(SGNODE *aNode) noexcept override
Definition: sg_index.cpp:108
The base class of all Scene Graph nodes.
Definition: sg_node.h:75
virtual bool WriteCache(std::ostream &aFile, SGNODE *parentNode)=0
Write this node's data to a binary cache file.
const char * GetName(void)
Definition: sg_node.cpp:146
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
S3D::SGTYPES GetNodeType(void) const noexcept
Return the type of this node instance.
Definition: sg_node.cpp:104
virtual bool AddChildNode(SGNODE *aNode)=0
SGNODE * m_Parent
Pointer to parent node; may be NULL for top level transform.
Definition: sg_node.h:227
std::string m_Name
name to use for referencing the entity by name.
Definition: sg_node.h:229
virtual void unlinkChildNode(const SGNODE *aNode)=0
Remove references to an owned child.
bool m_written
Set to true when the object has been written after a ReNameNodes().
Definition: sg_node.h:230
S3D::SGTYPES m_SGtype
Type of Scene Graph node.
Definition: sg_node.h:228
@ SGTYPE_FACESET
Definition: sg_types.h:40
@ SGTYPE_COORDINDEX
Definition: sg_types.h:42