32#include <wx/filename.h>
38#include "idf_parser.h"
39#include "vrml_layer.h"
41#define PLUGIN_3D_IDF_MAJOR 1
42#define PLUGIN_3D_IDF_MINOR 0
43#define PLUGIN_3D_IDF_PATCH 0
44#define PLUGIN_3D_IDF_REVNO 0
85static bool getOutlineModel( VRML_LAYER& model,
const std::list< IDF_OUTLINE* >* items );
89static bool addSegment( VRML_LAYER& model, IDF_SEGMENT* seg,
int icont,
int iseg );
102 setlocale( LC_NUMERIC,
"C" );
107 setlocale( LC_NUMERIC,
"" );
190 if( ( colorIdx == -1 ) && ( ++cidx >
NCOLORS ) )
199 return "PLUGIN_3D_IDF";
204 unsigned char* Revision )
237 static char fil0[] =
"IDF (*.idf)|*.idf";
238 static char fil1[] =
"IDF BRD v2/v3 (*.emn)|*.emn";
242 static char fil0[] =
"IDF (*.idf;*.IDF)|*.idf;*.IDF";
243 static char fil1[] =
"IDF BRD (*.emn;*.EMN)|*.emn;*.EMN";
275 if( aIndex < 0 || aIndex >=
NEXTS )
290 if( aIndex < 0 || aIndex >=
NFILS )
306 if(
nullptr == aFileName )
310 fname.Assign( wxString::FromUTF8Unchecked( aFileName ) );
312 wxString ext = fname.GetExt();
316 if( !ext.Cmp( wxT(
"idf" ) ) || !ext.Cmp( wxT(
"IDF" ) ) )
321 if( !ext.Cmp( wxT(
"emn" ) ) || !ext.Cmp( wxT(
"EMN" ) ) )
327#if defined( DEBUG_IDF ) && DEBUG_IDF > 3
330 wxFileName fn( aFileName );
331 wxString output = wxT(
"_idf-" );
332 output.append( fn.GetName() );
333 output.append( wxT(
".wrl" ) );
342static bool getOutlineModel( VRML_LAYER& model,
const std::list< IDF_OUTLINE* >* items )
345 if( items->size() < 1 )
351 std::list< IDF_OUTLINE* >::const_iterator scont = items->begin();
352 std::list< IDF_OUTLINE* >::const_iterator econt = items->end();
353 std::list<IDF_SEGMENT*>::iterator sseg;
354 std::list<IDF_SEGMENT*>::iterator eseg;
358 while( scont != econt )
360 nvcont = model.NewContour();
365 "* [INFO] cannot create an outline" ),
366 __FILE__, __FUNCTION__, __LINE__ );
371 if( (*scont)->size() < 1 )
374 "* [INFO] invalid contour: no vertices" ),
375 __FILE__, __FUNCTION__, __LINE__ );
380 sseg = (*scont)->begin();
381 eseg = (*scont)->end();
385 while( sseg != eseg )
389 if( !
addSegment( model, &lseg, nvcont, iseg ) )
392 "* [BUG] cannot add segment" ),
393 __FILE__, __FUNCTION__, __LINE__ );
409static bool addSegment( VRML_LAYER& model, IDF_SEGMENT* seg,
int icont,
int iseg )
414 if( seg->angle != 0.0 )
416 if( seg->IsCircle() )
422 "* [INFO] adding a circle to an existing vertex list" ),
423 __FILE__, __FUNCTION__, __LINE__ );
428 return model.AppendCircle( seg->center.x, seg->center.y, seg->radius, icont );
432 return model.AppendArc( seg->center.x, seg->center.y, seg->radius,
433 seg->offsetAngle, seg->angle, icont );
437 if( !model.AddVertex( icont, seg->startPoint.x, seg->startPoint.y ) )
447 vpcb.Tesselate(
nullptr );
448 std::vector< double > vertices;
449 std::vector< int > idxPlane;
450 std::vector< int > idxSide;
459 if( !vpcb.Get3DTriangles( vertices, idxPlane, idxSide, top, bottom ) )
462 "* [INFO] no vertex data" ),
463 __FILE__, __FUNCTION__, __LINE__ );
468 if( ( idxPlane.size() % 3 ) || ( idxSide.size() % 3 ) )
472 "* [BUG] index lists are not a multiple of 3 (not a triangle list)" ),
473 __FILE__, __FUNCTION__, __LINE__ );
478 std::vector< SGPOINT > vlist;
479 size_t nvert = vertices.size() / 3;
482 for(
size_t i = 0; i < nvert; ++i, j+= 3 )
483 vlist.emplace_back( vertices[j], vertices[j+1], vertices[j+2] );
500 coordIdx->
SetIndices( idxPlane.size(), &idxPlane[0] );
509 for(
size_t i = 0; i < j; ++i )
513 for(
size_t i = 0; i < j; ++i )
529 std::vector< int >::iterator sI = idxSide.begin();
530 std::vector< int >::iterator eI = idxSide.end();
583 "* [INFO] no valid outline data" ),
584 __FILE__, __FUNCTION__, __LINE__ );
589 vpcb.EnsureWinding( 0,
false );
591 double top = outline->GetThickness();
610 IDF3_BOARD brd( IDF3::CAD_ELEC );
611 IDF3_COMP_OUTLINE* outline =
nullptr;
613 outline = brd.GetComponentOutline( aFileName );
615 if(
nullptr == outline )
618 "* [INFO] Failed to read IDF data:\n"
620 "* [INFO] no outline for file '%s'" ),
621 __FILE__, __FUNCTION__, __LINE__,
637 IDF3_BOARD brd( IDF3::CAD_ELEC );
640 if( !brd.ReadFile( aFileName,
true ) )
643 "* [INFO] Error '%s' occurred reading IDF file: %s" ),
644 __FILE__, __FUNCTION__, __LINE__,
654 bool noBoard =
false;
656 bool noOther =
false;
658 if(
nullptr ==
makeBoard( brd, topNode ) )
667 if( noBoard && noComp && noOther )
679 if(
nullptr == aParent )
685 if( brd.GetBoardOutlinesSize() < 1 )
692 vpcb.EnsureWinding( 0,
false );
694 int nvcont = vpcb.GetNContours() - 1;
697 vpcb.EnsureWinding( nvcont--,
true );
700 const std::list<IDF_DRILL_DATA*>* drills = &brd.GetBoardDrills();
702 std::list<IDF_DRILL_DATA*>::const_iterator sd = drills->begin();
703 std::list<IDF_DRILL_DATA*>::const_iterator ed = drills->end();
707 vpcb.AddCircle( (*sd)->GetDrillXPos(), (*sd)->GetDrillYPos(),
708 (*sd)->GetDrillDia() / 2.0,
true );
712 std::map< std::string, IDF3_COMPONENT* >*
const comp = brd.GetComponents();
713 std::map< std::string, IDF3_COMPONENT* >::const_iterator sc = comp->begin();
714 std::map< std::string, IDF3_COMPONENT* >::const_iterator ec = comp->end();
718 drills = sc->second->GetDrills();
719 sd = drills->begin();
724 vpcb.AddCircle( (*sd)->GetDrillXPos(), (*sd)->GetDrillYPos(),
725 (*sd)->GetDrillDia() / 2.0,
true );
732 double top = brd.GetBoardThickness();
742 if(
nullptr == aParent )
747 double brdTop = brd.GetBoardThickness();
750 const std::map< std::string, IDF3_COMPONENT* >*
const comp = brd.GetComponents();
751 std::map< std::string, IDF3_COMPONENT* >::const_iterator sc = comp->begin();
752 std::map< std::string, IDF3_COMPONENT* >::const_iterator ec = comp->end();
754 std::list< IDF3_COMP_OUTLINE_DATA* >::const_iterator so;
755 std::list< IDF3_COMP_OUTLINE_DATA* >::const_iterator eo;
758 double tX, tY, tZ, tA;
762 std::map< std::string, SGNODE* > dataMap;
763 std::map< std::string, SGNODE* >::iterator dataItem;
764 IDF3_COMP_OUTLINE* pout;
768 sc->second->GetPosition( vX, vY, vA, lyr );
770 if( lyr == IDF3::LYR_BOTTOM )
775 so = sc->second->GetOutlinesData()->begin();
776 eo = sc->second->GetOutlinesData()->end();
780 if(
std::abs( (*so)->GetOutline()->GetThickness() ) < 0.001 )
786 (*so)->GetOffsets( tX, tY, tZ, tA );
791 pout = (IDF3_COMP_OUTLINE*)((*so)->GetOutline());
793 if(
nullptr == pout )
799 dataItem = dataMap.find( pout->GetUID() );
802 if( dataItem == dataMap.end() )
813 dataMap.insert( std::pair< std::string, SGNODE* >( pout->GetUID(), (
SGNODE*)sg ) );
837 double ang = -tA * M_PI / 360.0;
838 double sinA = sin( ang );
839 double cosA = cos( ang );
854 if( 0 == ncomponents )
863 if(
nullptr == aParent )
869 double brdTop = brd.GetBoardThickness();
873 const std::map< std::string, OTHER_OUTLINE* >*
const comp = brd.GetOtherOutlines();
874 std::map< std::string, OTHER_OUTLINE* >::const_iterator sc = comp->begin();
875 std::map< std::string, OTHER_OUTLINE* >::const_iterator ec = comp->end();
885 if(
std::abs( pout->GetThickness() ) < 0.001 )
898 vpcb.EnsureWinding( 0,
false );
900 nvcont = vpcb.GetNContours() - 1;
903 vpcb.EnsureWinding( nvcont--,
true );
905 if( pout->GetSide() == IDF3::LYR_BOTTOM )
908 bot = -pout->GetThickness();
913 top = bot + pout->GetThickness();
916 if(
nullptr ==
vrmlToSG( vpcb, -1, aParent, top, bot ) )
929 if( 0 == ncomponents )
describes 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
IFSG_COORDINDEX is the wrapper for SGCOORDINDEX.
bool NewNode(SGNODE *aParent) override
Function NewNode creates a new node to associate with this wrapper.
IFSG_COORDS is the wrapper for SGCOORDS.
bool NewNode(SGNODE *aParent) override
Function NewNode creates a new node to associate with this wrapper.
bool SetCoordsList(size_t aListSize, const SGPOINT *aCoordsList)
bool AddCoord(double aXValue, double aYValue, double aZValue)
IFSG_FACESET is the wrapper for the SGFACESET class.
bool NewNode(SGNODE *aParent) override
Function NewNode creates a new node to associate with this wrapper.
bool AddIndex(int aIndex)
Function AddIndex adds a single index to the list.
bool SetIndices(size_t nIndices, int *aIndexList)
Function SetIndices sets the number of indices and creates a copy of the given index data.
SGNODE * GetParent(void) const
Function GetParent returns a pointer to the parent SGNODE of this object or NULL if the object has no...
SGNODE * GetRawPtr(void) noexcept
Function GetRawPtr() returns the raw internal SGNODE pointer.
void Destroy(void)
Function Destroy deletes the object held by this wrapper.
bool AddChildNode(SGNODE *aNode)
Function AddChildNode adds a node as a child owned by this node.
bool AddRefNode(SGNODE *aNode)
Function AddRefNode adds a reference to an existing node which is not owned by (not a child of) this ...
IFSG_NORMALS is the wrapper for the SGNORMALS class.
bool NewNode(SGNODE *aParent) override
Function NewNode creates a new node to associate with this wrapper.
bool AddNormal(double aXValue, double aYValue, double aZValue)
IFSG_SHAPE is the wrapper for the SGSHAPE class.
bool NewNode(SGNODE *aParent) override
Function NewNode creates 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)
Function WriteVRML writes out the given node and its subnodes to a VRML2 file.
SGLIB_API SGVECTOR CalcTriNorm(const SGPOINT &p1, const SGPOINT &p2, const SGPOINT &p3)
Function CalcTriNorm returns the normal vector of a triangle described by vertices p1,...
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)
Function GetModelExtension.
bool CanRender(void)
Function CanRender.
#define PLUGIN_3D_IDF_MAJOR
#define PLUGIN_3D_IDF_PATCH
SCENEGRAPH * Load(char const *aFileName)
reads a model file and creates a generic display structure
char const * GetFileFilter(int aIndex)
Function GetFileFilter.
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)
Function GetPluginVersion retrieves the version of the instantiated plugin for informational purposes...
#define PLUGIN_3D_IDF_REVNO
const char * GetKicadPluginName(void)
Function GetKicadPluginName returns the name of the plugin instance; for example IDFv3.
int GetNExtensions(void)
Function GetNExtensions.
int GetNFilters(void)
Function GetNFilters.
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]