ADDED: Basic STEP manipulation utils available to Python.

This commit is contained in:
Alex Shvartzkop 2023-08-15 05:07:46 +03:00
parent 52feb38fd1
commit 1b8abdfde7
5 changed files with 413 additions and 1 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 NBEE Embedded Systems, Miguel Angel Ajo <miguelangel@nbee.es>
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -104,6 +104,7 @@ principle should be easily implemented by adapting the current STL containers.
#include <build_version.h>
#include <layer_ids.h>
#include <settings/settings_manager.h>
#include <pcbnew_utils_3d.h>
%}
// all the wx wrappers for wxString, wxPoint, wxRect, wxChar ..
@ -135,6 +136,7 @@ principle should be easily implemented by adapting the current STL containers.
%include build_version.h
%include layer_ids.h
%include settings/settings_manager.h
%include pcbnew_utils_3d.h
// Cast time_t to known type for Python
typedef long time_t;

View File

@ -20,6 +20,7 @@
#ifndef VECTOR3_H_
#define VECTOR3_H_
#include <stdint.h>
#include <limits>
#include <wx/debug.h>

View File

@ -380,6 +380,7 @@ set( PCBNEW_SCRIPTING_PYTHON_HELPERS
python/scripting/pcbnew_footprint_wizards.cpp
python/scripting/pcbnew_scripting_helpers.cpp
python/scripting/pcbnew_scripting.cpp
python/scripting/pcbnew_utils_3d.cpp
python/scripting/pcb_scripting_tool.cpp
)

View File

@ -0,0 +1,349 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 Alex Shvartzkop <dudesuchamazing@gmail.com>
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "pcbnew_utils_3d.h"
#include <memory>
#include <wx/filename.h>
#include <wx/wfstream.h>
#include <wx/log.h>
#include <TDocStd_Document.hxx>
#include <XCAFApp_Application.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <TopoDS.hxx>
#include <TopExp_Explorer.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <BRepTools.hxx>
#include <BRep_Builder.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepBuilderAPI_GTransform.hxx>
#include <STEPCAFControl_Reader.hxx>
#include <STEPCAFControl_Writer.hxx>
#include <Interface_Static.hxx>
#include <XCAFDoc_Color.hxx>
#include <Quantity_Color.hxx>
#include <ShapeCustom.hxx>
// precision for mesh creation; 0.07 should be good enough for ECAD viewing
#define USER_PREC ( 0.14 )
static void transformDoc( Handle( TDocStd_Document ) & source, Handle( TDocStd_Document ) & dest,
const gp_GTrsf& transform )
{
// transfer data from Source into a top level component of Dest
BRepBuilderAPI_GTransform brep( transform );
// s_assy = shape tool for the source
Handle( XCAFDoc_ShapeTool ) s_assy = XCAFDoc_DocumentTool::ShapeTool( source->Main() );
// retrieve all free shapes within the assembly
TDF_LabelSequence frshapes;
s_assy->GetFreeShapes( frshapes );
// d_assy = shape tool for the destination
Handle( XCAFDoc_ShapeTool ) d_assy = XCAFDoc_DocumentTool::ShapeTool( dest->Main() );
int nshapes = frshapes.Length();
int id = 1;
Handle( XCAFDoc_ColorTool ) scolor = XCAFDoc_DocumentTool::ColorTool( source->Main() );
Handle( XCAFDoc_ColorTool ) dcolor = XCAFDoc_DocumentTool::ColorTool( dest->Main() );
TopExp_Explorer dtop;
TopExp_Explorer stop;
while( id <= nshapes )
{
TopoDS_Shape shape = s_assy->GetShape( frshapes.Value( id ) );
if( !shape.IsNull() )
{
TopoDS_Shape transformed_shape( shape );
if( transform.Trsf().ScaleFactor() != 1.0 )
{
transformed_shape =
ShapeCustom::ScaleShape( shape, transform.Trsf().ScaleFactor() );
}
else
{
brep.Perform( shape, Standard_False );
if( brep.IsDone() )
transformed_shape = brep.Shape();
}
TDF_Label niulab = d_assy->AddShape( transformed_shape, false, false );
// check for per-surface colors
stop.Init( shape, TopAbs_FACE );
dtop.Init( d_assy->GetShape( niulab ), TopAbs_FACE );
while( stop.More() && dtop.More() )
{
Quantity_Color face_color;
TDF_Label tl;
// give priority to the base shape's color
if( s_assy->FindShape( stop.Current(), tl ) )
{
if( scolor->GetColor( tl, XCAFDoc_ColorSurf, face_color )
|| scolor->GetColor( tl, XCAFDoc_ColorGen, face_color )
|| scolor->GetColor( tl, XCAFDoc_ColorCurv, face_color ) )
{
dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorSurf );
}
}
else if( scolor->GetColor( stop.Current(), XCAFDoc_ColorSurf, face_color )
|| scolor->GetColor( stop.Current(), XCAFDoc_ColorGen, face_color )
|| scolor->GetColor( stop.Current(), XCAFDoc_ColorCurv, face_color ) )
{
dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorSurf );
}
stop.Next();
dtop.Next();
}
// check for per-solid colors
stop.Init( shape, TopAbs_SOLID );
dtop.Init( d_assy->GetShape( niulab ), TopAbs_SOLID, TopAbs_FACE );
while( stop.More() && dtop.More() )
{
Quantity_Color face_color;
TDF_Label tl;
// give priority to the base shape's color
if( s_assy->FindShape( stop.Current(), tl ) )
{
if( scolor->GetColor( tl, XCAFDoc_ColorSurf, face_color )
|| scolor->GetColor( tl, XCAFDoc_ColorGen, face_color )
|| scolor->GetColor( tl, XCAFDoc_ColorCurv, face_color ) )
{
dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorGen );
}
}
else if( scolor->GetColor( stop.Current(), XCAFDoc_ColorSurf, face_color )
|| scolor->GetColor( stop.Current(), XCAFDoc_ColorGen, face_color )
|| scolor->GetColor( stop.Current(), XCAFDoc_ColorCurv, face_color ) )
{
dcolor->SetColor( dtop.Current(), face_color, XCAFDoc_ColorSurf );
}
stop.Next();
dtop.Next();
}
}
++id;
};
}
VECTOR3D UTILS_BOX3D::GetCenter()
{
return VECTOR3D( ( m_min.x + m_max.x ) * 0.5, ( m_min.y + m_max.y ) * 0.5,
( m_min.z + m_max.z ) * 0.5 );
}
VECTOR3D UTILS_BOX3D::GetSize()
{
return VECTOR3D( m_max.x - m_min.x, m_max.y - m_min.y, m_max.z - m_min.z );
}
VECTOR3D& UTILS_BOX3D::Min()
{
return m_min;
}
VECTOR3D& UTILS_BOX3D::Max()
{
return m_max;
}
struct UTILS_STEP_MODEL::DATA
{
Handle( TDocStd_Document ) m_frontDoc;
Handle( TDocStd_Document ) m_backDoc;
STEPCAFControl_Reader m_cafReader;
};
UTILS_STEP_MODEL* UTILS_STEP_MODEL::LoadSTEP( const wxString& aFileName )
{
std::unique_ptr<UTILS_STEP_MODEL::DATA> data = std::make_unique<UTILS_STEP_MODEL::DATA>();
Handle( XCAFApp_Application ) m_app = XCAFApp_Application::GetApplication();
m_app->NewDocument( "MDTV-XCAF", data->m_frontDoc );
m_app->NewDocument( "MDTV-XCAF", data->m_backDoc );
STEPCAFControl_Reader reader;
IFSelect_ReturnStatus stat = reader.ReadFile( aFileName );
if( stat != IFSelect_RetDone )
return nullptr;
// Enable user-defined shape precision
if( !Interface_Static::SetIVal( "read.precision.mode", 1 ) )
return nullptr;
// Set the shape conversion precision to USER_PREC (default 0.0001 has too many triangles)
if( !Interface_Static::SetRVal( "read.precision.val", USER_PREC ) )
return nullptr;
// set other translation options
reader.SetColorMode( true ); // use model colors
reader.SetNameMode( true ); // use label names
reader.SetLayerMode( false ); // ignore LAYER data
if( !reader.Transfer( data->m_frontDoc ) )
return nullptr;
data->m_cafReader = reader;
UTILS_STEP_MODEL* model = new UTILS_STEP_MODEL();
model->m_data = data.release();
return model;
}
UTILS_STEP_MODEL::~UTILS_STEP_MODEL()
{
delete m_data;
}
UTILS_BOX3D UTILS_STEP_MODEL::GetBoundingBox()
{
Handle( XCAFDoc_ShapeTool ) assy =
XCAFDoc_DocumentTool::ShapeTool( m_data->m_frontDoc->Main() );
TDF_LabelSequence frshapes;
assy->GetFreeShapes( frshapes );
int nshapes = frshapes.Length();
Bnd_Box bbox;
UTILS_BOX3D result;
if( nshapes == 0 )
return result;
for( const TDF_Label& label : frshapes )
{
TopoDS_Shape shape = assy->GetShape( label );
BRepBndLib::Add( shape, bbox );
}
gp_Pnt min = bbox.CornerMin();
gp_Pnt max = bbox.CornerMax();
result.Min().x = min.X();
result.Min().y = min.Y();
result.Min().z = min.Z();
result.Max().x = max.X();
result.Max().y = max.Y();
result.Max().z = max.Z();
return result;
}
void UTILS_STEP_MODEL::Translate( double aX, double aY, double aZ )
{
// Create a translation transformation
gp_Trsf transform;
transform.SetTranslation( gp_Vec( aX, aY, aZ ) );
transformDoc( m_data->m_frontDoc, m_data->m_backDoc, transform );
std::swap( m_data->m_frontDoc, m_data->m_backDoc );
Handle( XCAFApp_Application ) m_app = XCAFApp_Application::GetApplication();
m_data->m_backDoc->Main().ForgetAllAttributes();
m_app->Close( m_data->m_backDoc );
m_app->NewDocument( "MDTV-XCAF", m_data->m_backDoc );
}
void UTILS_STEP_MODEL::Scale( double aScale )
{
// Create a scale transformation
gp_Trsf transform;
transform.SetScaleFactor( aScale );
transformDoc( m_data->m_frontDoc, m_data->m_backDoc, transform );
std::swap( m_data->m_frontDoc, m_data->m_backDoc );
Handle( XCAFApp_Application ) m_app = XCAFApp_Application::GetApplication();
m_data->m_backDoc->Main().ForgetAllAttributes();
m_app->Close( m_data->m_backDoc );
m_app->NewDocument( "MDTV-XCAF", m_data->m_backDoc );
}
bool UTILS_STEP_MODEL::SaveSTEP( const wxString& aFileName )
{
STEPCAFControl_Writer writer;
writer.SetColorMode( true );
writer.SetNameMode( true );
// To reduce file size
if( !Interface_Static::SetIVal( "write.surfacecurve.mode", 0 ) )
return false;
if( !writer.Transfer( m_data->m_frontDoc, STEPControl_AsIs ) )
return false;
if( writer.Write( aFileName ) != IFSelect_RetDone )
return false;
Handle( XCAFApp_Application ) m_app = XCAFApp_Application::GetApplication();
m_data->m_frontDoc->Main().ForgetAllAttributes();
m_data->m_backDoc->Main().ForgetAllAttributes();
m_app->Close( m_data->m_frontDoc );
m_app->Close( m_data->m_backDoc );
return true;
}

View File

@ -0,0 +1,59 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 Alex Shvartzkop <dudesuchamazing@gmail.com>
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef PCBNEW_UTILS_3D_H_
#define PCBNEW_UTILS_3D_H_
#include <wx/string.h>
#include <math/vector3.h>
class UTILS_BOX3D
{
VECTOR3D m_min;
VECTOR3D m_max;
public:
VECTOR3D& Min();
VECTOR3D& Max();
VECTOR3D GetCenter();
VECTOR3D GetSize();
};
class UTILS_STEP_MODEL
{
struct DATA;
DATA* m_data;
~UTILS_STEP_MODEL();
public:
UTILS_BOX3D GetBoundingBox();
void Translate( double aX, double aY, double aZ );
void Scale( double aScale );
bool SaveSTEP( const wxString& aFileName );
static UTILS_STEP_MODEL* LoadSTEP( const wxString& aFileName );
};
#endif // PCBNEW_UTILS_3D_H_