30#include <wx/filename.h>
36#include "idf_parser.h"
37#include "vrml_layer.h"
39#define PLUGIN_3D_IDF_MAJOR 1
40#define PLUGIN_3D_IDF_MINOR 0
41#define PLUGIN_3D_IDF_PATCH 0
42#define PLUGIN_3D_IDF_REVNO 0
83static bool getOutlineModel( VRML_LAYER& model,
const std::list< IDF_OUTLINE* >* items );
87static bool addSegment( VRML_LAYER& model, IDF_SEGMENT* seg,
int icont,
int iseg );
100 setlocale( LC_NUMERIC,
"C" );
105 setlocale( LC_NUMERIC,
"" );
188 if( ( colorIdx == -1 ) && ( ++cidx >
NCOLORS ) )
197 return "PLUGIN_3D_IDF";
202 unsigned char* Revision )
235 static char fil0[] =
"IDF (*.idf)|*.idf";
236 static char fil1[] =
"IDF BRD v2/v3 (*.emn)|*.emn";
240 static char fil0[] =
"IDF (*.idf;*.IDF)|*.idf;*.IDF";
241 static char fil1[] =
"IDF BRD (*.emn;*.EMN)|*.emn;*.EMN";
273 if( aIndex < 0 || aIndex >=
NEXTS )
288 if( aIndex < 0 || aIndex >=
NFILS )
304 if(
nullptr == aFileName )
308 fname.Assign( wxString::FromUTF8Unchecked( aFileName ) );
310 wxString ext = fname.GetExt();
314 if( !ext.Cmp( wxT(
"idf" ) ) || !ext.Cmp( wxT(
"IDF" ) ) )
319 if( !ext.Cmp( wxT(
"emn" ) ) || !ext.Cmp( wxT(
"EMN" ) ) )
325#if defined( DEBUG_IDF ) && DEBUG_IDF > 3
328 wxFileName fn( aFileName );
329 wxString output = wxT(
"_idf-" );
330 output.append( fn.GetName() );
331 output.append( wxT(
".wrl" ) );
340static bool getOutlineModel( VRML_LAYER& model,
const std::list< IDF_OUTLINE* >* items )
343 if( items->size() < 1 )
349 std::list< IDF_OUTLINE* >::const_iterator scont = items->begin();
350 std::list< IDF_OUTLINE* >::const_iterator econt = items->end();
351 std::list<IDF_SEGMENT*>::iterator sseg;
352 std::list<IDF_SEGMENT*>::iterator eseg;
356 while( scont != econt )
358 nvcont = model.NewContour();
363 "* [INFO] cannot create an outline" ),
364 __FILE__, __FUNCTION__, __LINE__ );
369 if( (*scont)->size() < 1 )
372 "* [INFO] invalid contour: no vertices" ),
373 __FILE__, __FUNCTION__, __LINE__ );
378 sseg = (*scont)->begin();
379 eseg = (*scont)->end();
383 while( sseg != eseg )
387 if( !
addSegment( model, &lseg, nvcont, iseg ) )
390 "* [BUG] cannot add segment" ),
391 __FILE__, __FUNCTION__, __LINE__ );
407static bool addSegment( VRML_LAYER& model, IDF_SEGMENT* seg,
int icont,
int iseg )
412 if( seg->angle != 0.0 )
414 if( seg->IsCircle() )
420 "* [INFO] adding a circle to an existing vertex list" ),
421 __FILE__, __FUNCTION__, __LINE__ );
426 return model.AppendCircle( seg->center.x, seg->center.y, seg->radius, icont );
430 return model.AppendArc( seg->center.x, seg->center.y, seg->radius,
431 seg->offsetAngle, seg->angle, icont );
435 if( !model.AddVertex( icont, seg->startPoint.x, seg->startPoint.y ) )
445 vpcb.Tesselate(
nullptr );
446 std::vector< double > vertices;
447 std::vector< int > idxPlane;
448 std::vector< int > idxSide;
457 if( !vpcb.Get3DTriangles( vertices, idxPlane, idxSide, top, bottom ) )
460 "* [INFO] no vertex data" ),
461 __FILE__, __FUNCTION__, __LINE__ );
466 if( ( idxPlane.size() % 3 ) || ( idxSide.size() % 3 ) )
470 "* [BUG] index lists are not a multiple of 3 (not a triangle list)" ),
471 __FILE__, __FUNCTION__, __LINE__ );
476 std::vector< SGPOINT > vlist;
477 size_t nvert = vertices.size() / 3;
480 for(
size_t i = 0; i < nvert; ++i, j+= 3 )
481 vlist.emplace_back( vertices[j], vertices[j+1], vertices[j+2] );
498 coordIdx->
SetIndices( idxPlane.size(), &idxPlane[0] );
507 for(
size_t i = 0; i < j; ++i )
511 for(
size_t i = 0; i < j; ++i )
527 std::vector< int >::iterator sI = idxSide.begin();
528 std::vector< int >::iterator eI = idxSide.end();
581 "* [INFO] no valid outline data" ),
582 __FILE__, __FUNCTION__, __LINE__ );
587 vpcb.EnsureWinding( 0,
false );
589 double top = outline->GetThickness();
608 IDF3_BOARD brd( IDF3::CAD_ELEC );
609 IDF3_COMP_OUTLINE* outline =
nullptr;
611 outline = brd.GetComponentOutline( aFileName );
613 if(
nullptr == outline )
616 "* [INFO] Failed to read IDF data:\n"
618 "* [INFO] no outline for file '%s'" ),
619 __FILE__, __FUNCTION__, __LINE__,
635 IDF3_BOARD brd( IDF3::CAD_ELEC );
638 if( !brd.ReadFile( aFileName,
true ) )
641 "* [INFO] Error '%s' occurred reading IDF file: %s" ),
642 __FILE__, __FUNCTION__, __LINE__,
652 bool noBoard =
false;
654 bool noOther =
false;
656 if(
nullptr ==
makeBoard( brd, topNode ) )
665 if( noBoard && noComp && noOther )
677 if(
nullptr == aParent )
683 if( brd.GetBoardOutlinesSize() < 1 )
690 vpcb.EnsureWinding( 0,
false );
692 int nvcont = vpcb.GetNContours() - 1;
695 vpcb.EnsureWinding( nvcont--,
true );
698 const std::list<IDF_DRILL_DATA*>* drills = &brd.GetBoardDrills();
700 std::list<IDF_DRILL_DATA*>::const_iterator sd = drills->begin();
701 std::list<IDF_DRILL_DATA*>::const_iterator ed = drills->end();
705 vpcb.AddCircle( (*sd)->GetDrillXPos(), (*sd)->GetDrillYPos(),
706 (*sd)->GetDrillDia() / 2.0,
true );
710 std::map< std::string, IDF3_COMPONENT* >*
const comp = brd.GetComponents();
711 std::map< std::string, IDF3_COMPONENT* >::const_iterator sc = comp->begin();
712 std::map< std::string, IDF3_COMPONENT* >::const_iterator ec = comp->end();
716 drills = sc->second->GetDrills();
717 sd = drills->begin();
722 vpcb.AddCircle( (*sd)->GetDrillXPos(), (*sd)->GetDrillYPos(),
723 (*sd)->GetDrillDia() / 2.0,
true );
730 double top = brd.GetBoardThickness();
740 if(
nullptr == aParent )
745 double brdTop = brd.GetBoardThickness();
748 const std::map< std::string, IDF3_COMPONENT* >*
const comp = brd.GetComponents();
749 std::map< std::string, IDF3_COMPONENT* >::const_iterator sc = comp->begin();
750 std::map< std::string, IDF3_COMPONENT* >::const_iterator ec = comp->end();
752 std::list< IDF3_COMP_OUTLINE_DATA* >::const_iterator so;
753 std::list< IDF3_COMP_OUTLINE_DATA* >::const_iterator eo;
756 double tX, tY, tZ, tA;
760 std::map< std::string, SGNODE* > dataMap;
761 std::map< std::string, SGNODE* >::iterator dataItem;
762 IDF3_COMP_OUTLINE* pout;
766 sc->second->GetPosition( vX, vY, vA, lyr );
768 if( lyr == IDF3::LYR_BOTTOM )
773 so = sc->second->GetOutlinesData()->begin();
774 eo = sc->second->GetOutlinesData()->end();
778 if(
std::abs( (*so)->GetOutline()->GetThickness() ) < 0.001 )
784 (*so)->GetOffsets( tX, tY, tZ, tA );
789 pout = (IDF3_COMP_OUTLINE*)((*so)->GetOutline());
791 if(
nullptr == pout )
797 dataItem = dataMap.find( pout->GetUID() );
800 if( dataItem == dataMap.end() )
811 dataMap.insert( std::pair< std::string, SGNODE* >( pout->GetUID(), (
SGNODE*)sg ) );
835 double ang = -tA * M_PI / 360.0;
836 double sinA = sin( ang );
837 double cosA = cos( ang );
852 if( 0 == ncomponents )
861 if(
nullptr == aParent )
867 double brdTop = brd.GetBoardThickness();
871 const std::map< std::string, OTHER_OUTLINE* >*
const comp = brd.GetOtherOutlines();
872 std::map< std::string, OTHER_OUTLINE* >::const_iterator sc = comp->begin();
873 std::map< std::string, OTHER_OUTLINE* >::const_iterator ec = comp->end();
883 if(
std::abs( pout->GetThickness() ) < 0.001 )
896 vpcb.EnsureWinding( 0,
false );
898 nvcont = vpcb.GetNContours() - 1;
901 vpcb.EnsureWinding( nvcont--,
true );
903 if( pout->GetSide() == IDF3::LYR_BOTTOM )
906 bot = -pout->GetThickness();
911 top = bot + pout->GetThickness();
914 if(
nullptr ==
vrmlToSG( vpcb, -1, aParent, top, bot ) )
927 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]