KiCad PCB EDA Suite
sg_normals.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  *
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 #include <iostream>
25 #include <sstream>
26 #include <wx/log.h>
27 
28 #include "3d_cache/sg/sg_normals.h"
29 #include "3d_cache/sg/sg_helpers.h"
30 
31 
32 SGNORMALS::SGNORMALS( SGNODE* aParent ) : SGNODE( aParent )
33 {
35 
36  if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
37  {
38  m_Parent = NULL;
39 
40 #ifdef DEBUG
41  std::ostringstream ostr;
42  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
43  ostr << " * [BUG] inappropriate parent to SGNORMALS (type ";
44  ostr << aParent->GetNodeType() << ")";
45  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
46 #endif
47  }
48  else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
49  {
50  m_Parent->AddChildNode( this );
51  }
52 
53  return;
54 }
55 
56 
58 {
59  norms.clear();
60  return;
61 }
62 
63 
64 bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
65 {
66  if( NULL != m_Parent )
67  {
68  if( aParent == m_Parent )
69  return true;
70 
71  // handle the change in parents
72  if( notify )
73  m_Parent->unlinkChildNode( this );
74 
75  m_Parent = NULL;
76 
77  if( NULL == aParent )
78  return true;
79  }
80 
81  // only a SGFACESET may be parent to a SGNORMALS
82  if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
83  return false;
84 
85  m_Parent = aParent;
86 
87  if( m_Parent )
88  m_Parent->AddChildNode( this );
89 
90  return true;
91 }
92 
93 
94 SGNODE* SGNORMALS::FindNode(const char *aNodeName, const SGNODE *aCaller)
95 {
96  if( NULL == aNodeName || 0 == aNodeName[0] )
97  return NULL;
98 
99  if( !m_Name.compare( aNodeName ) )
100  return this;
101 
102  return NULL;
103 }
104 
105 
106 void SGNORMALS::unlinkChildNode( const SGNODE* aCaller )
107 {
108  #ifdef DEBUG
109  std::ostringstream ostr;
110  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
111  ostr << " * [BUG] unexpected code branch; node should have no children or refs";
112  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
113  #endif
114 
115  return;
116 }
117 
118 
119 void SGNORMALS::unlinkRefNode( const SGNODE* aCaller )
120 {
121  #ifdef DEBUG
122  std::ostringstream ostr;
123  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
124  ostr << " * [BUG] unexpected code branch; node should have no children or refs";
125  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
126  #endif
127 
128  return;
129 }
130 
131 
133 {
134  #ifdef DEBUG
135  std::ostringstream ostr;
136  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
137  ostr << " * [BUG] this node does not accept children or refs";
138  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
139  #endif
140 
141  return false;
142 }
143 
144 
146 {
147  #ifdef DEBUG
148  std::ostringstream ostr;
149  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
150  ostr << " * [BUG] this node does not accept children or refs";
151  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
152  #endif
153 
154  return false;
155 }
156 
157 
158 bool SGNORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
159 {
160  if( norms.empty() )
161  {
162  aListSize = 0;
163  aNormalList = NULL;
164  return false;
165  }
166 
167  aListSize = norms.size();
168  aNormalList = &norms[0];
169  return true;
170 }
171 
172 
173 void SGNORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
174 {
175  norms.clear();
176 
177  if( 0 == aListSize || NULL == aNormalList )
178  return;
179 
180  for( int i = 0; i < (int)aListSize; ++i )
181  norms.push_back( aNormalList[i] );
182 
183  return;
184 }
185 
186 
187 void SGNORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
188 {
189  norms.push_back( SGVECTOR( aXValue, aYValue, aZValue ) );
190  return;
191 }
192 
193 
194 void SGNORMALS::AddNormal( const SGVECTOR& aNormal )
195 {
196  norms.push_back( aNormal );
197  return;
198 }
199 
200 
202 {
203  m_written = false;
204 
205  // rename this node
206  m_Name.clear();
207  GetName();
208 }
209 
210 
211 bool SGNORMALS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
212 {
213  if( norms.empty() )
214  return false;
215 
216  if( aReuseFlag )
217  {
218  if( !m_written )
219  {
220  aFile << " normal DEF " << GetName() << " Normal { vector [\n ";
221  m_written = true;
222  }
223  else
224  {
225  aFile << " normal USE " << GetName() << "\n";
226  return true;
227  }
228  }
229  else
230  {
231  aFile << " normal Normal { vector [\n ";
232  }
233 
234  std::string tmp;
235  size_t n = norms.size();
236  bool nline = false;
237 
238  for( size_t i = 0; i < n; )
239  {
240  S3D::FormatVector( tmp, norms[i] );
241  aFile << tmp ;
242  ++i;
243 
244  if( i < n )
245  {
246  aFile << ",";
247 
248  if( nline )
249  {
250  aFile << "\n ";
251  nline = false;
252  }
253  else
254  {
255  nline = true;
256  }
257 
258  }
259  }
260 
261  aFile << "] }\n";
262 
263  return true;
264 }
265 
266 
267 bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
268 {
269  if( NULL == parentNode )
270  {
271  if( NULL == m_Parent )
272  {
273  #ifdef DEBUG
274  std::ostringstream ostr;
275  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
276  ostr << " * [BUG] corrupt data; m_aParent is NULL";
277  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
278  #endif
279 
280  return false;
281  }
282 
283  SGNODE* np = m_Parent;
284 
285  while( NULL != np->GetParent() )
286  np = np->GetParent();
287 
288  if( np->WriteCache( aFile, NULL ) )
289  {
290  m_written = true;
291  return true;
292  }
293 
294  return false;
295  }
296 
297  if( parentNode != m_Parent )
298  {
299  #ifdef DEBUG
300  std::ostringstream ostr;
301  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
302  ostr << " * [BUG] corrupt data; parentNode != m_aParent";
303  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
304  #endif
305 
306  return false;
307  }
308 
309  if( !aFile.good() )
310  {
311  #ifdef DEBUG
312  std::ostringstream ostr;
313  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
314  ostr << " * [INFO] bad stream";
315  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
316  #endif
317 
318  return false;
319  }
320 
321  aFile << "[" << GetName() << "]";
322  size_t npts = norms.size();
323  aFile.write( (char*)&npts, sizeof(size_t) );
324 
325  for( size_t i = 0; i < npts; ++i )
326  S3D::WriteVector( aFile, norms[i] );
327 
328  if( aFile.fail() )
329  return false;
330 
331  m_written = true;
332  return true;
333 }
334 
335 
336 bool SGNORMALS::ReadCache( std::istream& aFile, SGNODE* parentNode )
337 {
338  if( !norms.empty() )
339  {
340  #ifdef DEBUG
341  std::ostringstream ostr;
342  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
343  ostr << " * [BUG] non-empty node";
344  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
345  #endif
346 
347  return false;
348  }
349 
350  size_t npts;
351  aFile.read( (char*)&npts, sizeof(size_t) );
352  SGVECTOR tmp;
353 
354  if( aFile.fail() )
355  return false;
356 
357  for( size_t i = 0; i < npts; ++i )
358  {
359  if( !S3D::ReadVector( aFile, tmp ) || aFile.fail() )
360  return false;
361 
362  norms.push_back( tmp );
363  }
364 
365  return true;
366 }
void ReNameNodes(void) override
Function ReNameNodes renames a node and all its child nodes in preparation for Write() operations...
Definition: sg_normals.cpp:201
SGNODE * FindNode(const char *aNodeName, const SGNODE *aCaller) override
Function FindNode searches the tree of linked nodes and returns a reference to the first node found w...
Definition: sg_normals.cpp:94
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Function WriteCache write's this node's data to a binary cache file; the data includes all data of ch...
Definition: sg_normals.cpp:267
SGNODE * m_Parent
Definition: sg_node.h:83
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Function SetParent sets the parent SGNODE of this object.
Definition: sg_normals.cpp:64
bool ReadVector(std::istream &aFile, SGVECTOR &aVector)
Definition: sg_helpers.cpp:309
defines a set of vertex normals for a scene graph object
Class SGNODE represents the base class of all Scene Graph nodes.
Definition: sg_node.h:76
S3D::SGTYPES GetNodeType(void) const
Function GetNodeType returns the type of this node instance.
Definition: sg_node.cpp:108
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Function ReadCache Reads binary format data from a cache file.
Definition: sg_normals.cpp:336
virtual ~SGNORMALS()
Definition: sg_normals.cpp:57
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Function WriteVRML writes this node's data to a VRML file; this includes all data of child and refere...
Definition: sg_normals.cpp:211
void unlinkRefNode(const SGNODE *aNode) override
Function unlinkRef removes pointers to a referenced node; it is invoked by the referenced node upon d...
Definition: sg_normals.cpp:119
void FormatVector(std::string &result, const SGVECTOR &aVector)
Definition: sg_helpers.cpp:126
const char * GetName(void)
Definition: sg_node.cpp:150
bool m_written
Definition: sg_node.h:86
SGNODE * GetParent(void) const
Function GetParent returns a pointer to the parent SGNODE of this object or NULL if the object has no...
Definition: sg_node.cpp:114
virtual void unlinkChildNode(const SGNODE *aNode)=0
Function unlinkChild removes references to an owned child; it is invoked by the child upon destructio...
bool WriteVector(std::ostream &aFile, const SGVECTOR &aVector)
Definition: sg_helpers.cpp:178
std::vector< SGVECTOR > norms
Definition: sg_normals.h:38
void AddNormal(double aXValue, double aYValue, double aZValue)
Definition: sg_normals.cpp:187
bool AddChildNode(SGNODE *aNode) override
Definition: sg_normals.cpp:145
std::string m_Name
Definition: sg_node.h:85
virtual bool WriteCache(std::ostream &aFile, SGNODE *parentNode)=0
Function WriteCache write's this node's data to a binary cache file; the data includes all data of ch...
bool AddRefNode(SGNODE *aNode) override
Definition: sg_normals.cpp:132
S3D::SGTYPES m_SGtype
Definition: sg_node.h:84
virtual bool AddChildNode(SGNODE *aNode)=0
void unlinkChildNode(const SGNODE *aNode) override
Function unlinkChild removes references to an owned child; it is invoked by the child upon destructio...
Definition: sg_normals.cpp:106
defines a number of macro functions to aid in repetitious code which is probably best expressed as a ...
void SetNormalList(size_t aListSize, const SGVECTOR *aNormalList)
Definition: sg_normals.cpp:173
bool GetNormalList(size_t &aListSize, SGVECTOR *&aNormalList)
Definition: sg_normals.cpp:158
SGNORMALS(SGNODE *aParent)
Definition: sg_normals.cpp:32