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 <[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
33#ifndef SG_HELPERS_H
34#define SG_HELPERS_H
35
36#include <iostream>
37#include <string>
38#include <algorithm>
39#include <vector>
42#include <glm/glm.hpp>
43
44class SGNORMALS;
45class SGCOORDS;
46class 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
198namespace 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
An object to maintain a coordinate index list.
Definition: sg_coordindex.h:43
Define a vertex coordinate set for a scenegraph object.
Definition: sg_coords.h:41
Define a set of vertex normals for a scene graph object.
Definition: sg_normals.h:39
bool ReadVector(std::istream &aFile, SGVECTOR &aVector)
Definition: sg_helpers.cpp:280
bool ReadPoint(std::istream &aFile, SGPOINT &aPoint)
Definition: sg_helpers.cpp:267
bool WritePoint(std::ostream &aFile, const SGPOINT &aPoint)
Definition: sg_helpers.cpp:152
bool WriteColor(std::ostream &aFile, const SGCOLOR &aColor)
Definition: sg_helpers.cpp:180
bool CalcTriangleNormals(std::vector< SGPOINT > coords, std::vector< int > &index, std::vector< SGVECTOR > &norms)
Definition: sg_helpers.cpp:353
void FormatColor(std::string &result, const SGCOLOR &aColor)
Definition: sg_helpers.cpp:135
void FormatFloat(std::string &result, double value)
Definition: sg_helpers.cpp:37
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
void FormatVector(std::string &result, const SGVECTOR &aVector)
Definition: sg_helpers.cpp:118
void FormatPoint(std::string &result, const SGPOINT &point)
Definition: sg_helpers.cpp:103
bool degenerate(glm::dvec3 *pts) noexcept
Definition: sg_helpers.cpp:310
SGTYPES
Definition: sg_types.h:35
bool ReadColor(std::istream &aFile, SGCOLOR &aColor)
Definition: sg_helpers.cpp:295
void FormatOrientation(std::string &result, const SGVECTOR &axis, double rotation)
Definition: sg_helpers.cpp:82
defines the low level classes common to scene graph nodes
defines the types of intermediate scene graph objects