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 )
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]