26#include <wx/filename.h>
32#include "idf_parser.h"
33#include "vrml_layer.h"
35#define PLUGIN_3D_IDF_MAJOR 1
36#define PLUGIN_3D_IDF_MINOR 0
37#define PLUGIN_3D_IDF_PATCH 0
38#define PLUGIN_3D_IDF_REVNO 0
83static bool addSegment( VRML_LAYER&
model, IDF_SEGMENT* seg,
int icont,
int iseg );
96 setlocale( LC_NUMERIC,
"C" );
101 setlocale( LC_NUMERIC,
"" );
184 if( ( colorIdx == -1 ) && ( ++cidx >
NCOLORS ) )
193 return "PLUGIN_3D_IDF";
198 unsigned char* Revision )
231 static char fil0[] =
"IDF (*.idf)|*.idf";
232 static char fil1[] =
"IDF BRD v2/v3 (*.emn)|*.emn";
236 static char fil0[] =
"IDF (*.idf;*.IDF)|*.idf;*.IDF";
237 static char fil1[] =
"IDF BRD (*.emn;*.EMN)|*.emn;*.EMN";
269 if( aIndex < 0 || aIndex >=
NEXTS )
284 if( aIndex < 0 || aIndex >=
NFILS )
300 if(
nullptr == aFileName )
304 fname.Assign( wxString::FromUTF8Unchecked( aFileName ) );
306 wxString ext = fname.GetExt();
310 if( !ext.Cmp( wxT(
"idf" ) ) || !ext.Cmp( wxT(
"IDF" ) ) )
315 if( !ext.Cmp( wxT(
"emn" ) ) || !ext.Cmp( wxT(
"EMN" ) ) )
321#if defined( DEBUG_IDF ) && DEBUG_IDF > 3
324 wxFileName fn( aFileName );
325 wxString
output = wxT(
"_idf-" );
326 output.append( fn.GetName() );
327 output.append( wxT(
".wrl" ) );
339 if( items->size() < 1 )
345 std::list< IDF_OUTLINE* >::const_iterator scont = items->begin();
346 std::list< IDF_OUTLINE* >::const_iterator econt = items->end();
347 std::list<IDF_SEGMENT*>::iterator sseg;
348 std::list<IDF_SEGMENT*>::iterator eseg;
352 while( scont != econt )
354 nvcont =
model.NewContour();
359 "* [INFO] cannot create an outline" ),
360 __FILE__, __FUNCTION__, __LINE__ );
365 if( (*scont)->size() < 1 )
368 "* [INFO] invalid contour: no vertices" ),
369 __FILE__, __FUNCTION__, __LINE__ );
374 sseg = (*scont)->begin();
375 eseg = (*scont)->end();
379 while( sseg != eseg )
386 "* [BUG] cannot add segment" ),
387 __FILE__, __FUNCTION__, __LINE__ );
408 if( seg->angle != 0.0 )
410 if( seg->IsCircle() )
416 "* [INFO] adding a circle to an existing vertex list" ),
417 __FILE__, __FUNCTION__, __LINE__ );
422 return model.AppendCircle( seg->center.x, seg->center.y, seg->radius, icont );
426 return model.AppendArc( seg->center.x, seg->center.y, seg->radius,
427 seg->offsetAngle, seg->angle, icont );
431 if( !
model.AddVertex( icont, seg->startPoint.x, seg->startPoint.y ) )
441 vpcb.Tesselate(
nullptr );
442 std::vector< double > vertices;
443 std::vector< int > idxPlane;
444 std::vector< int > idxSide;
453 if( !vpcb.Get3DTriangles( vertices, idxPlane, idxSide,
top, bottom ) )
456 "* [INFO] no vertex data" ),
457 __FILE__, __FUNCTION__, __LINE__ );
462 if( ( idxPlane.size() % 3 ) || ( idxSide.size() % 3 ) )
466 "* [BUG] index lists are not a multiple of 3 (not a triangle list)" ),
467 __FILE__, __FUNCTION__, __LINE__ );
472 std::vector< SGPOINT > vlist;
473 size_t nvert = vertices.size() / 3;
476 for(
size_t i = 0; i < nvert; ++i, j+= 3 )
477 vlist.emplace_back( vertices[j], vertices[j+1], vertices[j+2] );
494 coordIdx->
SetIndices( idxPlane.size(), &idxPlane[0] );
503 for(
size_t i = 0; i < j; ++i )
507 for(
size_t i = 0; i < j; ++i )
523 std::vector< int >::iterator sI = idxSide.begin();
524 std::vector< int >::iterator eI = idxSide.end();
577 "* [INFO] no valid outline data" ),
578 __FILE__, __FUNCTION__, __LINE__ );
583 vpcb.EnsureWinding( 0,
false );
585 double top = outline->GetThickness();
604 IDF3_BOARD brd( IDF3::CAD_ELEC );
605 IDF3_COMP_OUTLINE* outline =
nullptr;
607 outline = brd.GetComponentOutline( aFileName );
609 if(
nullptr == outline )
612 "* [INFO] Failed to read IDF data:\n"
614 "* [INFO] no outline for file '%s'" ),
615 __FILE__, __FUNCTION__, __LINE__,
631 IDF3_BOARD brd( IDF3::CAD_ELEC );
634 if( !brd.ReadFile( aFileName,
true ) )
637 "* [INFO] Error '%s' occurred reading IDF file: %s" ),
638 __FILE__, __FUNCTION__, __LINE__,
648 bool noBoard =
false;
650 bool noOther =
false;
652 if(
nullptr ==
makeBoard( brd, topNode ) )
661 if( noBoard && noComp && noOther )
673 if(
nullptr == aParent )
679 if( brd.GetBoardOutlinesSize() < 1 )
686 vpcb.EnsureWinding( 0,
false );
688 int nvcont = vpcb.GetNContours() - 1;
691 vpcb.EnsureWinding( nvcont--,
true );
694 const std::list<IDF_DRILL_DATA*>* drills = &brd.GetBoardDrills();
696 std::list<IDF_DRILL_DATA*>::const_iterator sd = drills->begin();
697 std::list<IDF_DRILL_DATA*>::const_iterator ed = drills->end();
701 vpcb.AddCircle( (*sd)->GetDrillXPos(), (*sd)->GetDrillYPos(),
702 (*sd)->GetDrillDia() / 2.0,
true );
706 std::map< std::string, IDF3_COMPONENT* >*
const comp = brd.GetComponents();
707 std::map< std::string, IDF3_COMPONENT* >::const_iterator sc =
comp->begin();
708 std::map< std::string, IDF3_COMPONENT* >::const_iterator ec =
comp->end();
712 drills = sc->second->GetDrills();
713 sd = drills->begin();
718 vpcb.AddCircle( (*sd)->GetDrillXPos(), (*sd)->GetDrillYPos(),
719 (*sd)->GetDrillDia() / 2.0,
true );
726 double top = brd.GetBoardThickness();
736 if(
nullptr == aParent )
741 double brdTop = brd.GetBoardThickness();
744 const std::map< std::string, IDF3_COMPONENT* >*
const comp = brd.GetComponents();
745 std::map< std::string, IDF3_COMPONENT* >::const_iterator sc =
comp->begin();
746 std::map< std::string, IDF3_COMPONENT* >::const_iterator ec =
comp->end();
748 std::list< IDF3_COMP_OUTLINE_DATA* >::const_iterator so;
749 std::list< IDF3_COMP_OUTLINE_DATA* >::const_iterator eo;
752 double tX, tY, tZ, tA;
756 std::map< std::string, SGNODE* > dataMap;
757 std::map< std::string, SGNODE* >::iterator dataItem;
758 IDF3_COMP_OUTLINE* pout;
762 sc->second->GetPosition( vX, vY,
vA, lyr );
764 if( lyr == IDF3::LYR_BOTTOM )
769 so = sc->second->GetOutlinesData()->begin();
770 eo = sc->second->GetOutlinesData()->end();
774 if(
std::abs( (*so)->GetOutline()->GetThickness() ) < 0.001 )
780 (*so)->GetOffsets( tX, tY, tZ, tA );
785 pout = (IDF3_COMP_OUTLINE*)((*so)->GetOutline());
787 if(
nullptr == pout )
793 dataItem = dataMap.find( pout->GetUID() );
796 if( dataItem == dataMap.end() )
807 dataMap.insert( std::pair< std::string, SGNODE* >( pout->GetUID(), (
SGNODE*)sg ) );
831 double ang = -tA *
M_PI / 360.0;
832 double sinA = sin( ang );
833 double cosA = cos( ang );
848 if( 0 == ncomponents )
857 if(
nullptr == aParent )
863 double brdTop = brd.GetBoardThickness();
867 const std::map< std::string, OTHER_OUTLINE* >*
const comp = brd.GetOtherOutlines();
868 std::map< std::string, OTHER_OUTLINE* >::const_iterator sc =
comp->begin();
869 std::map< std::string, OTHER_OUTLINE* >::const_iterator ec =
comp->end();
879 if(
std::abs( pout->GetThickness() ) < 0.001 )
892 vpcb.EnsureWinding( 0,
false );
894 nvcont = vpcb.GetNContours() - 1;
897 vpcb.EnsureWinding( nvcont--,
true );
899 if( pout->GetSide() == IDF3::LYR_BOTTOM )
902 bot = -pout->GetThickness();
907 top = bot + pout->GetThickness();
910 if(
nullptr ==
vrmlToSG( vpcb, -1, aParent,
top, bot ) )
923 if( 0 == ncomponents )
Describe the runtime-loadable interface to support loading and parsing of 3D models.
bool SetDiffuse(float aRVal, float aGVal, float aBVal)
bool SetSpecular(float aRVal, float aGVal, float aBVal)
bool SetShininess(float aShininess) noexcept
The wrapper for SGCOORDINDEX.
bool NewNode(SGNODE *aParent) override
Create a new node to associate with this wrapper.
The wrapper for SGCOORDS.
bool NewNode(SGNODE *aParent) override
Create a new node to associate with this wrapper.
bool SetCoordsList(size_t aListSize, const SGPOINT *aCoordsList)
bool AddCoord(double aXValue, double aYValue, double aZValue)
The wrapper for the SGFACESET class.
bool NewNode(SGNODE *aParent) override
Create a new node to associate with this wrapper.
bool AddIndex(int aIndex)
Add a single index to the list.
bool SetIndices(size_t nIndices, int *aIndexList)
Set the number of indices and creates a copy of the given index data.
SGNODE * GetParent(void) const
Return a pointer to the parent SGNODE of this object or NULL if the object has no parent (ie.
SGNODE * GetRawPtr(void) noexcept
Return the raw internal SGNODE pointer.
void Destroy(void)
Delete the object held by this wrapper.
bool AddChildNode(SGNODE *aNode)
Add a node as a child owned by this node.
bool AddRefNode(SGNODE *aNode)
Add a reference to an existing node which is not owned by (not a child of) this node.
The wrapper for the SGNORMALS class.
bool NewNode(SGNODE *aParent) override
Create a new node to associate with this wrapper.
bool AddNormal(double aXValue, double aYValue, double aZValue)
The wrapper for the SGSHAPE class.
bool NewNode(SGNODE *aParent) override
Create a new node to associate with this wrapper.
Define the basic data set required to represent a 3D model.
The base class of all Scene Graph nodes.
void SetVector(double aXVal, double aYVal, double aZVal)
const wxChar *const traceIdfPlugin
Flag to enable IDF plugin trace output.
collects header files for all SG* wrappers and the API
SGLIB_API bool WriteVRML(const char *filename, bool overwrite, SGNODE *aTopNode, bool reuse, bool renameNodes)
Write out the given node and its subnodes to a VRML2 file.
SGLIB_API SGVECTOR CalcTriNorm(const SGPOINT &p1, const SGPOINT &p2, const SGPOINT &p3)
Return the normal vector of a triangle described by vertices p1, p2, p3.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
static bool addSegment(VRML_LAYER &model, IDF_SEGMENT *seg, int icont, int iseg)
static bool makeComponents(IDF3_BOARD &brd, SGNODE *aParent)
static bool getOutlineModel(VRML_LAYER &model, const std::list< IDF_OUTLINE * > *items)
static struct FILE_DATA file_data
char const * GetModelExtension(int aIndex)
#define PLUGIN_3D_IDF_MAJOR
#define PLUGIN_3D_IDF_PATCH
SCENEGRAPH * Load(char const *aFileName)
Read a model file and creates a generic display structure.
char const * GetFileFilter(int aIndex)
static SCENEGRAPH * makeBoard(IDF3_BOARD &brd, SGNODE *aParent)
#define PLUGIN_3D_IDF_MINOR
static SCENEGRAPH * loadIDFOutline(const wxString &aFileName)
void GetPluginVersion(unsigned char *Major, unsigned char *Minor, unsigned char *Patch, unsigned char *Revision)
Retrieve the version of the instantiated plugin for informational purposes.
#define PLUGIN_3D_IDF_REVNO
const char * GetKicadPluginName(void)
Return the name of the plugin instance, for example IDFv3.
static SCENEGRAPH * loadIDFBoard(const wxString &aFileName)
static bool makeOtherOutlines(IDF3_BOARD &brd, SGNODE *aParent)
static SCENEGRAPH * addOutline(IDF3_COMP_OUTLINE *outline, int idxColor, SGNODE *aParent)
static SGNODE * getColor(IFSG_SHAPE &shape, int colorIdx)
static SCENEGRAPH * vrmlToSG(VRML_LAYER &vpcb, int idxColor, SGNODE *aParent, double top, double bottom)
char const * extensions[NEXTS]
char const * filters[NFILS]
KIBIS top(path, &reporter)