KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcbnew_utils_3d.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) 2023 Alex Shvartzkop <[email protected]>
5 * Copyright (C) 2023 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
25#include "pcbnew_utils_3d.h"
26
27#include <memory>
28
29#include <wx/filename.h>
30#include <wx/wfstream.h>
31#include <wx/log.h>
32
33#include <TDocStd_Document.hxx>
34#include <XCAFApp_Application.hxx>
35#include <XCAFDoc_DocumentTool.hxx>
36#include <XCAFDoc_ShapeTool.hxx>
37#include <XCAFDoc_ColorTool.hxx>
38
39#include <TopoDS.hxx>
40#include <TopExp_Explorer.hxx>
41
42#include <Bnd_Box.hxx>
43#include <BRepBndLib.hxx>
44
45#include <BRepTools.hxx>
46#include <BRep_Builder.hxx>
47#include <BRepBuilderAPI_Transform.hxx>
48#include <BRepBuilderAPI_GTransform.hxx>
49
50#include <STEPCAFControl_Reader.hxx>
51#include <STEPCAFControl_Writer.hxx>
52#include <Interface_Static.hxx>
53
54#include <XCAFDoc_Color.hxx>
55#include <Quantity_Color.hxx>
56#include <ShapeCustom.hxx>
57
58// precision for mesh creation; 0.07 should be good enough for ECAD viewing
59#define USER_PREC ( 0.14 )
60
61
62static void transformDoc( Handle( TDocStd_Document ) & source, Handle( TDocStd_Document ) & dest,
63 const gp_GTrsf& transform )
64{
65 // transfer data from Source into a top level component of Dest
66 BRepBuilderAPI_GTransform brep( transform );
67
68 // s_assy = shape tool for the source
69 Handle( XCAFDoc_ShapeTool ) s_assy = XCAFDoc_DocumentTool::ShapeTool( source->Main() );
70
71 // retrieve all free shapes within the assembly
72 TDF_LabelSequence frshapes;
73 s_assy->GetFreeShapes( frshapes );
74
75 // d_assy = shape tool for the destination
76 Handle( XCAFDoc_ShapeTool ) d_assy = XCAFDoc_DocumentTool::ShapeTool( dest->Main() );
77
78 int nshapes = frshapes.Length();
79 int id = 1;
80 Handle( XCAFDoc_ColorTool ) scolor = XCAFDoc_DocumentTool::ColorTool( source->Main() );
81 Handle( XCAFDoc_ColorTool ) dcolor = XCAFDoc_DocumentTool::ColorTool( dest->Main() );
82 TopExp_Explorer dtop;
83 TopExp_Explorer stop;
84
85 while( id <= nshapes )
86 {
87 TopoDS_Shape shape = s_assy->GetShape( frshapes.Value( id ) );
88
89 if( !shape.IsNull() )
90 {
91 TopoDS_Shape transformed_shape( shape );
92
93 if( transform.Trsf().ScaleFactor() != 1.0 )
94 {
95 transformed_shape =
96 ShapeCustom::ScaleShape( shape, transform.Trsf().ScaleFactor() );
97 }
98 else
99 {
100 brep.Perform( shape, Standard_False );
101
102 if( brep.IsDone() )
103 transformed_shape = brep.Shape();
104 }
105
106 TDF_Label niulab = d_assy->AddShape( transformed_shape, false, false );
107
108 // check for per-surface colors
109 stop.Init( shape, TopAbs_FACE );
110 dtop.Init( d_assy->GetShape( niulab ), TopAbs_FACE );
111
112 while( stop.More() && dtop.More() )
113 {
114 Quantity_Color face_color;
115
116 TDF_Label tl;
117
118 // give priority to the base shape's color
119 if( s_assy->FindShape( stop.Current(), tl ) )
120 {
121 if( scolor->GetColor( tl, XCAFDoc_ColorSurf, face_color )
122 || scolor->GetColor( tl, XCAFDoc_ColorGen, face_color )
123 || scolor->GetColor( tl, XCAFDoc_ColorCurv, face_color ) )
124 {
125 dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorSurf );
126 }
127 }
128 else if( scolor->GetColor( stop.Current(), XCAFDoc_ColorSurf, face_color )
129 || scolor->GetColor( stop.Current(), XCAFDoc_ColorGen, face_color )
130 || scolor->GetColor( stop.Current(), XCAFDoc_ColorCurv, face_color ) )
131 {
132 dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorSurf );
133 }
134
135 stop.Next();
136 dtop.Next();
137 }
138
139 // check for per-solid colors
140 stop.Init( shape, TopAbs_SOLID );
141 dtop.Init( d_assy->GetShape( niulab ), TopAbs_SOLID, TopAbs_FACE );
142
143 while( stop.More() && dtop.More() )
144 {
145 Quantity_Color face_color;
146
147 TDF_Label tl;
148
149 // give priority to the base shape's color
150 if( s_assy->FindShape( stop.Current(), tl ) )
151 {
152 if( scolor->GetColor( tl, XCAFDoc_ColorSurf, face_color )
153 || scolor->GetColor( tl, XCAFDoc_ColorGen, face_color )
154 || scolor->GetColor( tl, XCAFDoc_ColorCurv, face_color ) )
155 {
156 dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorGen );
157 }
158 }
159 else if( scolor->GetColor( stop.Current(), XCAFDoc_ColorSurf, face_color )
160 || scolor->GetColor( stop.Current(), XCAFDoc_ColorGen, face_color )
161 || scolor->GetColor( stop.Current(), XCAFDoc_ColorCurv, face_color ) )
162 {
163 dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorSurf );
164 }
165
166 stop.Next();
167 dtop.Next();
168 }
169 }
170
171 ++id;
172 };
173}
174
175
177{
178 return VECTOR3D( ( m_min.x + m_max.x ) * 0.5, ( m_min.y + m_max.y ) * 0.5,
179 ( m_min.z + m_max.z ) * 0.5 );
180}
181
182
184{
185 return VECTOR3D( m_max.x - m_min.x, m_max.y - m_min.y, m_max.z - m_min.z );
186}
187
188
190{
191 return m_min;
192}
193
194
196{
197 return m_max;
198}
199
200
202{
203 Handle( TDocStd_Document ) m_frontDoc;
204 Handle( TDocStd_Document ) m_backDoc;
205 STEPCAFControl_Reader m_cafReader;
206};
207
208
209UTILS_STEP_MODEL* UTILS_STEP_MODEL::LoadSTEP( const wxString& aFileName )
210{
211 std::unique_ptr<UTILS_STEP_MODEL::DATA> data = std::make_unique<UTILS_STEP_MODEL::DATA>();
212
213 Handle( XCAFApp_Application ) m_app = XCAFApp_Application::GetApplication();
214 m_app->NewDocument( "MDTV-XCAF", data->m_frontDoc );
215 m_app->NewDocument( "MDTV-XCAF", data->m_backDoc );
216
217 STEPCAFControl_Reader reader;
218 IFSelect_ReturnStatus stat = reader.ReadFile( aFileName.ToStdString().c_str() );
219
220 if( stat != IFSelect_RetDone )
221 return nullptr;
222
223 // Enable user-defined shape precision
224 if( !Interface_Static::SetIVal( "read.precision.mode", 1 ) )
225 return nullptr;
226
227 // Set the shape conversion precision to USER_PREC (default 0.0001 has too many triangles)
228 if( !Interface_Static::SetRVal( "read.precision.val", USER_PREC ) )
229 return nullptr;
230
231 // set other translation options
232 reader.SetColorMode( true ); // use model colors
233 reader.SetNameMode( true ); // use label names
234 reader.SetLayerMode( false ); // ignore LAYER data
235
236 if( !reader.Transfer( data->m_frontDoc ) )
237 return nullptr;
238
239 data->m_cafReader = reader;
240
241 UTILS_STEP_MODEL* model = new UTILS_STEP_MODEL();
242 model->m_data = data.release();
243 return model;
244}
245
246
248{
249 delete m_data;
250}
251
252
254{
255 Handle( XCAFDoc_ShapeTool ) assy =
256 XCAFDoc_DocumentTool::ShapeTool( m_data->m_frontDoc->Main() );
257
258 TDF_LabelSequence frshapes;
259 assy->GetFreeShapes( frshapes );
260
261 int nshapes = frshapes.Length();
262 Bnd_Box bbox;
263 UTILS_BOX3D result;
264
265 if( nshapes == 0 )
266 return result;
267
268 for( const TDF_Label& label : frshapes )
269 {
270 TopoDS_Shape shape = assy->GetShape( label );
271 BRepBndLib::Add( shape, bbox );
272 }
273
274 gp_Pnt min = bbox.CornerMin();
275 gp_Pnt max = bbox.CornerMax();
276
277 result.Min().x = min.X();
278 result.Min().y = min.Y();
279 result.Min().z = min.Z();
280
281 result.Max().x = max.X();
282 result.Max().y = max.Y();
283 result.Max().z = max.Z();
284
285 return result;
286}
287
288
289void UTILS_STEP_MODEL::Translate( double aX, double aY, double aZ )
290{
291 // Create a translation transformation
292 gp_Trsf transform;
293 transform.SetTranslation( gp_Vec( aX, aY, aZ ) );
294
295 transformDoc( m_data->m_frontDoc, m_data->m_backDoc, transform );
296 std::swap( m_data->m_frontDoc, m_data->m_backDoc );
297
298 Handle( XCAFApp_Application ) m_app = XCAFApp_Application::GetApplication();
299
300 m_data->m_backDoc->Main().ForgetAllAttributes();
301 m_app->Close( m_data->m_backDoc );
302 m_app->NewDocument( "MDTV-XCAF", m_data->m_backDoc );
303}
304
305
306void UTILS_STEP_MODEL::Scale( double aScale )
307{
308
309 // Create a scale transformation
310 gp_Trsf transform;
311 transform.SetScaleFactor( aScale );
312
313 transformDoc( m_data->m_frontDoc, m_data->m_backDoc, transform );
314 std::swap( m_data->m_frontDoc, m_data->m_backDoc );
315
316 Handle( XCAFApp_Application ) m_app = XCAFApp_Application::GetApplication();
317
318 m_data->m_backDoc->Main().ForgetAllAttributes();
319 m_app->Close( m_data->m_backDoc );
320 m_app->NewDocument( "MDTV-XCAF", m_data->m_backDoc );
321}
322
323
324bool UTILS_STEP_MODEL::SaveSTEP( const wxString& aFileName )
325{
326 STEPCAFControl_Writer writer;
327 writer.SetColorMode( true );
328 writer.SetNameMode( true );
329
330 // To reduce file size
331 if( !Interface_Static::SetIVal( "write.surfacecurve.mode", 0 ) )
332 return false;
333
334 if( !writer.Transfer( m_data->m_frontDoc, STEPControl_AsIs ) )
335 return false;
336
337 if( writer.Write( aFileName.ToStdString().c_str() ) != IFSelect_RetDone )
338 return false;
339
340 Handle( XCAFApp_Application ) m_app = XCAFApp_Application::GetApplication();
341
342 m_data->m_frontDoc->Main().ForgetAllAttributes();
343 m_data->m_backDoc->Main().ForgetAllAttributes();
344
345 m_app->Close( m_data->m_frontDoc );
346 m_app->Close( m_data->m_backDoc );
347
348 return true;
349}
VECTOR3D GetCenter()
VECTOR3D m_max
VECTOR3D & Min()
VECTOR3D & Max()
VECTOR3D m_min
VECTOR3D GetSize()
static UTILS_STEP_MODEL * LoadSTEP(const wxString &aFileName)
bool SaveSTEP(const wxString &aFileName)
void Scale(double aScale)
UTILS_BOX3D GetBoundingBox()
void Translate(double aX, double aY, double aZ)
T y
Definition: vector3.h:64
T z
Definition: vector3.h:65
T x
Definition: vector3.h:63
static void transformDoc(Handle(TDocStd_Document) &source, Handle(TDocStd_Document) &dest, const gp_GTrsf &transform)
#define USER_PREC
Handle(TDocStd_Document) m_frontDoc
STEPCAFControl_Reader m_cafReader
Handle(TDocStd_Document) m_backDoc
VECTOR3< double > VECTOR3D
Definition: vector3.h:214