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