KiCad PCB EDA Suite
sg_helpers.h
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 
32 #ifndef SG_HELPERS_H
33 #define SG_HELPERS_H
34 
35 #include <iostream>
36 #include <string>
37 #include <algorithm>
38 #include <vector>
39 #include "plugins/3dapi/sg_base.h"
40 #include "plugins/3dapi/sg_types.h"
41 #include <glm/glm.hpp>
42 
43 class SGNORMALS;
44 class SGCOORDS;
45 class SGCOORDINDEX;
46 
47 // Function to drop references within an SGNODE
48 // The node being destroyed must remove itself from the object reference's
49 // backpointer list in order to avoid a segfault.
50 #define DROP_REFS( aType, aList ) do { \
51  std::vector< aType* >::iterator sL = aList.begin(); \
52  std::vector< aType* >::iterator eL = aList.end(); \
53  while( sL != eL ) { \
54  ((SGNODE*)*sL)->delNodeRef( this ); \
55  ++sL; \
56  } \
57  aList.clear(); \
58  } while( 0 )
59 
60 
61 // Function to delete owned objects within an SGNODE
62 // The owned object's parent is set to NULL before
63 // deletion to avoid a redundant 'unlinkChildNode' call.
64 #define DEL_OBJS( aType, aList ) do { \
65  std::vector< aType* >::iterator sL = aList.begin(); \
66  std::vector< aType* >::iterator eL = aList.end(); \
67  while( sL != eL ) { \
68  ((SGNODE*)*sL)->SetParent( NULL, false ); \
69  delete *sL; \
70  ++sL; \
71  } \
72  aList.clear(); \
73  } while( 0 )
74 
75 
76 // Function to unlink a child or reference node when that child or
77 // reference node is being destroyed.
78 #define UNLINK_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
79  if( aNodeID == aNode->GetNodeType() ) { \
80  std::vector< aType* >* oSL; \
81  std::vector< aType* >::iterator sL; \
82  std::vector< aType* >::iterator eL; \
83  if( isChild ) { \
84  oSL = &aOwnedList; \
85  sL = oSL->begin(); \
86  eL = oSL->end(); \
87  while( sL != eL ) { \
88  if( (SGNODE*)*sL == aNode ) { \
89  oSL->erase( sL ); \
90  return; \
91  } \
92  ++sL; \
93  } \
94  } else { \
95  oSL = &aRefList; \
96  sL = oSL->begin(); \
97  eL = oSL->end(); \
98  while( sL != eL ) { \
99  if( (SGNODE*)*sL == aNode ) { \
100  delNodeRef( this ); \
101  oSL->erase( sL ); \
102  return; \
103  } \
104  ++sL; \
105  } \
106  } \
107  return; \
108  } } while( 0 )
109 
110 
111 // Function to check a node type, check for an existing reference,
112 // and add the node type to the reference list if applicable
113 #define ADD_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
114  if( aNodeID == aNode->GetNodeType() ) { \
115  std::vector< aType* >::iterator sL; \
116  sL = std::find( aOwnedList.begin(), aOwnedList.end(), aNode ); \
117  if( sL != aOwnedList.end() ) return true; \
118  sL = std::find( aRefList.begin(), aRefList.end(), aNode ); \
119  if( sL != aRefList.end() ) return true; \
120  if( isChild ) { \
121  SGNODE* ppn = (SGNODE*)aNode->GetParent(); \
122  if( NULL != ppn ) { \
123  if( this != ppn ) { \
124  std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
125  std::cerr << " * [BUG] object '" << aNode->GetName(); \
126  std::cerr << "' has multiple parents '" << ppn->GetName() << "', '"; \
127  std::cerr << m_Name << "'\n"; \
128  return false; \
129  } \
130  } \
131  aOwnedList.push_back( (aType*)aNode ); \
132  aNode->SetParent( this, false ); \
133  } else { \
134  /*if( NULL == aNode->GetParent() ) { \
135  std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
136  std::cerr << " * [BUG] object '" << aNode->GetName(); \
137  std::cerr << "' has no parent\n"; \
138  std::cerr << " * [INFO] possible copy assignment or copy constructor bug\n"; \
139  return false; \
140  } */ \
141  aRefList.push_back( (aType*)aNode ); \
142  aNode->addNodeRef( this ); \
143  } \
144  return true; \
145  } } while( 0 )
146 
147 
148 // Function to find a node object given a (non-unique) node name
149 #define FIND_NODE( aType, aName, aNodeList, aCallingNode ) do { \
150  std::vector< aType* >::iterator sLA = aNodeList.begin(); \
151  std::vector< aType* >::iterator eLA = aNodeList.end(); \
152  SGNODE* psg = NULL; \
153  while( sLA != eLA ) { \
154  if( (SGNODE*)*sLA != aCallingNode ) { \
155  psg = (SGNODE*) (*sLA)->FindNode( aName, this ); \
156  if( NULL != psg) \
157  return psg; \
158  } \
159  ++sLA; \
160  } } while ( 0 )
161 
162 namespace S3D
163 {
164  bool degenerate( glm::dvec3* pts );
165 
166  //
167  // Normals calculations from triangles
168  //
169 
170  /*
171  * Function CalcTriangleNormals
172  * takes an array of 3D coordinates and its corresponding index set and calculates
173  * the normals assuming that indices are given in CCW order. Care must be taken in
174  * using this function to ensure that:
175  * (a) all coordinates are indexed; unindexed coordinates are assigned normal(0,0,1);
176  * when dealing with VRML models which may list and reuse one large coordinate set it
177  * is necessary to gather all index sets and perform this operation only once.
178  * (b) index sets must represent triangles (multiple of 3 indices) and must not be
179  * degenerate - that is all indices and coordinates in a triad must be unique.
180  *
181  * @param coords is the array of 3D vertices
182  * @param index is the array of 3x vertex indices (triads)
183  * @param norms is an empty array which holds the normals corresponding to each vector
184  * @return true on success; otherwise false.
185  */
186  bool CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >& index,
187  std::vector< SGVECTOR >& norms );
188 
189  //
190  // VRML related functions
191  //
192 
193  // formats a floating point number for text output to a VRML file
194  void FormatFloat( std::string& result, double value );
195 
196  // format orientation data for VRML output
197  void FormatOrientation( std::string& result, const SGVECTOR& axis, double rotation );
198 
199  // format point data for VRML output
200  void FormatPoint( std::string& result, const SGPOINT& point );
201 
202  // format vector data for VRML output
203  void FormatVector( std::string& result, const SGVECTOR& aVector );
204 
205  // format Color data for VRML output
206  void FormatColor( std::string& result, const SGCOLOR& aColor );
207 
208  //
209  // Cache related WRITE functions
210  //
211 
212  // write out an XYZ vertex
213  bool WritePoint( std::ostream& aFile, const SGPOINT& aPoint );
214 
215  // write out a unit vector
216  bool WriteVector( std::ostream& aFile, const SGVECTOR& aVector );
217 
218  // write out an RGB color
219  bool WriteColor( std::ostream& aFile, const SGCOLOR& aColor );
220 
221  //
222  // Cache related READ functions
223  //
224 
235  S3D::SGTYPES ReadTag( std::istream& aFile, std::string& aName );
236 
237  // read an XYZ vertex
238  bool ReadPoint( std::istream& aFile, SGPOINT& aPoint );
239 
240  // read a unit vector
241  bool ReadVector( std::istream& aFile, SGVECTOR& aVector );
242 
243  // read an RGB color
244  bool ReadColor( std::istream& aFile, SGCOLOR& aColor );
245 };
246 
247 #endif // SG_HELPERS_H
void FormatOrientation(std::string &result, const SGVECTOR &axis, double rotation)
Definition: sg_helpers.cpp:85
defines the types of intermediate scene graph objects
Class SGCOORDINDEX is a class which maintains a coordinate index list.
Definition: sg_coordindex.h:44
void FormatPoint(std::string &result, const SGPOINT &point)
Definition: sg_helpers.cpp:108
bool ReadColor(std::istream &aFile, SGCOLOR &aColor)
Definition: sg_helpers.cpp:324
void FormatColor(std::string &result, const SGCOLOR &aColor)
Definition: sg_helpers.cpp:146
bool ReadVector(std::istream &aFile, SGVECTOR &aVector)
Definition: sg_helpers.cpp:309
bool CalcTriangleNormals(std::vector< SGPOINT > coords, std::vector< int > &index, std::vector< SGVECTOR > &norms)
Definition: sg_helpers.cpp:384
bool WriteColor(std::ostream &aFile, const SGCOLOR &aColor)
Definition: sg_helpers.cpp:193
void FormatFloat(std::string &result, double value)
Definition: sg_helpers.cpp:37
void FormatVector(std::string &result, const SGVECTOR &aVector)
Definition: sg_helpers.cpp:126
defines the low level classes common to scene graph nodes
S3D::SGTYPES ReadTag(std::istream &aFile, std::string &aName)
Function ReadTag reads the text tag of a binary cache file which is the NodeTag and unique ID number ...
Definition: sg_helpers.cpp:208
bool WriteVector(std::ostream &aFile, const SGVECTOR &aVector)
Definition: sg_helpers.cpp:178
bool WritePoint(std::ostream &aFile, const SGPOINT &aPoint)
Definition: sg_helpers.cpp:165
SGTYPES
Definition: sg_types.h:34
bool ReadPoint(std::istream &aFile, SGPOINT &aPoint)
Definition: sg_helpers.cpp:296
bool degenerate(glm::dvec3 *pts)
Definition: sg_helpers.cpp:339