KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sg_coords.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 The 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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <iostream>
22#include <sstream>
23#include <wx/log.h>
24
29
30
31SGCOORDS::SGCOORDS( SGNODE* aParent ) : SGNODE( aParent )
32{
34
35 if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
36 {
37 m_Parent = nullptr;
38
39 wxLogTrace( MASK_3D_SG,
40 wxT( "%s:%s:%d * [BUG] inappropriate parent to SGCOORDS (type %s)" ),
41 __FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
42 }
43 else if( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
44 {
45 m_Parent->AddChildNode( this );
46 }
47}
48
49
51{
52 coords.clear();
53}
54
55
56bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
57{
58 if( nullptr != m_Parent )
59 {
60 if( aParent == m_Parent )
61 return true;
62
63 // handle the change in parents
64 if( notify )
65 m_Parent->unlinkChildNode( this );
66
67 m_Parent = nullptr;
68
69 if( nullptr == aParent )
70 return true;
71 }
72
73 // only a SGFACESET may be parent to a SGCOORDS
74 if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
75 return false;
76
77 m_Parent = aParent;
78
79 if( m_Parent )
80 m_Parent->AddChildNode( this );
81
82 return true;
83}
84
85
86SGNODE* SGCOORDS::FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept
87{
88 if( nullptr == aNodeName || 0 == aNodeName[0] )
89 return nullptr;
90
91 if( !m_Name.compare( aNodeName ) )
92 return this;
93
94 return nullptr;
95}
96
97
98void SGCOORDS::unlinkChildNode( const SGNODE* aCaller ) noexcept
99{
100 wxCHECK( aCaller, /* void */ );
101}
102
103
104void SGCOORDS::unlinkRefNode( const SGNODE* aCaller ) noexcept
105{
106 wxCHECK( aCaller, /* void */ );
107}
108
109
110bool SGCOORDS::AddRefNode( SGNODE* aNode ) noexcept
111{
112 wxCHECK( aNode, false );
113
114 return false;
115}
116
117
118bool SGCOORDS::AddChildNode( SGNODE* aNode ) noexcept
119{
120 wxCHECK( aNode, false );
121
122 return false;
123}
124
125
126bool SGCOORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
127{
128 if( coords.empty() )
129 {
130 aListSize = 0;
131 aCoordsList = nullptr;
132 return false;
133 }
134
135 aListSize = coords.size();
136 aCoordsList = &coords[0];
137 return true;
138}
139
140
141void SGCOORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
142{
143 coords.clear();
144
145 if( 0 == aListSize || nullptr == aCoordsList )
146 return;
147
148 for( size_t i = 0; i < aListSize; ++i )
149 coords.push_back( aCoordsList[i] );
150}
151
152
153void SGCOORDS::AddCoord( double aXValue, double aYValue, double aZValue )
154{
155 coords.emplace_back( aXValue, aYValue, aZValue );
156}
157
158
159void SGCOORDS::AddCoord( const SGPOINT& aPoint )
160{
161 coords.push_back( aPoint );
162}
163
164
166{
167 m_written = false;
168
169 // rename this node
170 m_Name.clear();
171 GetName();
172}
173
174
175bool SGCOORDS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
176{
177 if( coords.empty() )
178 return false;
179
180 if( aReuseFlag )
181 {
182 if( !m_written )
183 {
184 aFile << " coord DEF " << GetName() << " Coordinate { point [\n ";
185 m_written = true;
186 }
187 else
188 {
189 aFile << " coord USE " << GetName() << "\n";
190 return true;
191 }
192 }
193 else
194 {
195 aFile << " coord Coordinate { point [\n ";
196 }
197
198 std::string tmp;
199 size_t n = coords.size();
200 bool nline = false;
201 SGPOINT pt;
202
203 for( size_t i = 0; i < n; )
204 {
205 // ensure VRML output has 1U = 0.1 inch as per legacy kicad expectations
206 pt = coords[i];
207 pt.x /= 2.54;
208 pt.y /= 2.54;
209 pt.z /= 2.54;
210 S3D::FormatPoint( tmp, pt );
211 aFile << tmp ;
212 ++i;
213
214 if( i < n )
215 {
216 aFile << ",";
217
218 if( nline )
219 {
220 aFile << "\n ";
221 nline = false;
222 }
223 else
224 {
225 nline = true;
226 }
227
228 }
229 }
230
231 aFile << "] }\n";
232
233 return true;
234}
235
236
237bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
238{
239 if( nullptr == parentNode )
240 {
241 wxCHECK( m_Parent, false );
242
243 SGNODE* np = m_Parent;
244
245 while( nullptr != np->GetParent() )
246 np = np->GetParent();
247
248 if( np->WriteCache( aFile, nullptr ) )
249 {
250 m_written = true;
251 return true;
252 }
253
254 return false;
255 }
256
257 wxCHECK( parentNode == m_Parent, false );
258
259 if( !aFile.good() )
260 {
261 wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
262 __FILE__, __FUNCTION__, __LINE__ );
263
264 return false;
265 }
266
267 aFile << "[" << GetName() << "]";
268 size_t npts = coords.size();
269 aFile.write( (char*)&npts, sizeof(size_t) );
270
271 for( size_t i = 0; i < npts; ++i )
272 S3D::WritePoint( aFile, coords[i] );
273
274 if( aFile.fail() )
275 return false;
276
277 m_written = true;
278 return true;
279}
280
281
282bool SGCOORDS::ReadCache( std::istream& aFile, SGNODE* parentNode )
283{
284 wxCHECK( coords.empty(), false );
285
286 size_t npts;
287 aFile.read( (char*) &npts, sizeof( size_t ) );
288 SGPOINT tmp;
289
290 if( aFile.fail() )
291 return false;
292
293 for( size_t i = 0; i < npts; ++i )
294 {
295 if( !S3D::ReadPoint( aFile, tmp ) || aFile.fail() )
296 return false;
297
298 coords.push_back( tmp );
299 }
300
301 return true;
302}
303
304
305bool SGCOORDS::CalcNormals( SGFACESET* callingNode, SGNODE** aPtr )
306{
307 if( aPtr )
308 *aPtr = nullptr;
309
310 if( nullptr == m_Parent || nullptr == callingNode )
311 return false;
312
313 // the parent and all references must have indices; collect all
314 // indices into one std::vector<>
315 std::vector< int > ilist;
316 SGNORMALS* np = nullptr;
317
318 if( callingNode == m_Parent )
319 {
320 ((SGFACESET*)m_Parent)->GatherCoordIndices( ilist );
321
322 std::list< SGNODE* >::iterator sB = m_BackPointers.begin();
323 std::list< SGNODE* >::iterator eB = m_BackPointers.end();
324
325 while( sB != eB )
326 {
327 SGFACESET* fp = (SGFACESET*)(*sB);
328 fp->GatherCoordIndices( ilist );
329 ++sB;
330 }
331
332 np = ( (SGFACESET*) m_Parent )->m_Normals;
333
334 if( !np )
335 np = new SGNORMALS( m_Parent );
336
337 }
338 else
339 {
340 callingNode->GatherCoordIndices( ilist );
341 np = callingNode->m_Normals;
342
343 if( !np )
344 np = new SGNORMALS( callingNode );
345
346 }
347
348 if( S3D::CalcTriangleNormals( coords, ilist, np->norms ) )
349 {
350 if( aPtr )
351 *aPtr = np;
352
353 return true;
354 }
355
356 delete np;
357
358 return false;
359}
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Write this node's data to a binary cache file.
void unlinkChildNode(const SGNODE *aNode) noexcept override
Remove references to an owned child.
Definition sg_coords.cpp:98
void unlinkRefNode(const SGNODE *aNode) noexcept override
Remove pointers to a referenced node.
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Writes this node's data to a VRML file.
std::vector< SGPOINT > coords
Definition sg_coords.h:68
bool AddRefNode(SGNODE *aNode) noexcept override
void AddCoord(double aXValue, double aYValue, double aZValue)
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Reads binary format data from a cache file.
SGCOORDS(SGNODE *aParent)
Definition sg_coords.cpp:31
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_coords.cpp:86
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Set the parent SGNODE of this object.
Definition sg_coords.cpp:56
bool AddChildNode(SGNODE *aNode) noexcept override
bool GetCoordsList(size_t &aListSize, SGPOINT *&aCoordsList)
void ReNameNodes(void) override
Rename a node and all its child nodes in preparation for write operations.
virtual ~SGCOORDS()
Definition sg_coords.cpp:50
void SetCoordsList(size_t aListSize, const SGPOINT *aCoordsList)
bool CalcNormals(SGFACESET *callingNode, SGNODE **aPtr=nullptr)
Calculate normals for this coordinate list and sets the normals list in the parent SGFACESET.
Define an indexed face set for a scenegraph.
Definition sg_faceset.h:43
void GatherCoordIndices(std::vector< int > &aIndexList)
Add all internal coordinate indices to the given list in preparation for a normals calculation.
SGNORMALS * m_Normals
Definition sg_faceset.h:78
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:142
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:106
S3D::SGTYPES GetNodeType(void) const noexcept
Return the type of this node instance.
Definition sg_node.cpp:100
std::list< SGNODE * > m_BackPointers
nodes which hold a reference to this.
Definition sg_node.h:222
SGNODE * m_Parent
Pointer to parent node; may be NULL for top level transform.
Definition sg_node.h:223
SGNODE(SGNODE *aParent)
Definition sg_node.cpp:72
std::string m_Name
name to use for referencing the entity by name.
Definition sg_node.h:225
bool m_written
Set to true when the object has been written after a ReNameNodes().
Definition sg_node.h:226
S3D::SGTYPES m_SGtype
Type of Scene Graph node.
Definition sg_node.h:224
Define a set of vertex normals for a scene graph object.
Definition sg_normals.h:35
std::vector< SGVECTOR > norms
Definition sg_normals.h:60
double z
Definition sg_base.h:68
double x
Definition sg_base.h:66
double y
Definition sg_base.h:67
bool ReadPoint(std::istream &aFile, SGPOINT &aPoint)
bool WritePoint(std::ostream &aFile, const SGPOINT &aPoint)
bool CalcTriangleNormals(std::vector< SGPOINT > coords, std::vector< int > &index, std::vector< SGVECTOR > &norms)
void FormatPoint(std::string &result, const SGPOINT &point)
@ SGTYPE_FACESET
Definition sg_types.h:37
@ SGTYPE_COORDS
Definition sg_types.h:38
Define a number of macros to aid in repetitious code which is probably best expressed as a preprocess...