kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #23852
PATCH: IDF tools
The attached patch makes the following changes to the IDF
tool 'dxf2idf':
1. DXF units are now correctly scaled to mm
2. Polylines are now supported
3. LWPolylines are now supported
- Cirilo
=== modified file 'utils/idftools/dxf2idf.cpp'
--- utils/idftools/dxf2idf.cpp 2014-02-05 09:27:21 +0000
+++ utils/idftools/dxf2idf.cpp 2016-03-21 10:16:01 +0000
@@ -29,6 +29,13 @@
// differences in angle smaller than MIN_ANG are considered equal
#define MIN_ANG (0.01)
+// min and max bulge bracketing min. arc before transition to line segment
+// and max. arc limit
+// MIN_BULGE = 0.002 ~0.45 degrees
+// MAX_BULGE = 2000 ~89.97 degrees
+#define MIN_BULGE 0.002
+#define MAX_BULGE 2000.0
+
DXF2IDF::~DXF2IDF()
{
while( !lines.empty() )
@@ -60,22 +67,12 @@
{
IDF_POINT p1, p2;
- p1.x = data.basePoint.x;
- p1.y = data.basePoint.y;
- p2.x = data.secPoint.x;
- p2.y = data.secPoint.y;
-
- IDF_SEGMENT* seg = new IDF_SEGMENT( p1, p2 );
-
- if( !seg )
- {
- std::cerr << "* FAULT: could not add a linear segment to the outline\n";
- }
- else
- {
- lines.push_back( seg );
- }
-
+ p1.x = data.basePoint.x * m_scale;
+ p1.y = data.basePoint.y * m_scale;
+ p2.x = data.secPoint.x * m_scale;
+ p2.y = data.secPoint.y * m_scale;
+
+ insertLine( p1, p2 );
return;
}
@@ -84,22 +81,16 @@
{
IDF_POINT p1, p2;
- p1.x = data.basePoint.x;
- p1.y = data.basePoint.y;
+ p1.x = data.basePoint.x * m_scale;
+ p1.y = data.basePoint.y * m_scale;
- p2.x = p1.x + data.radious;
+ p2.x = p1.x + data.radious * m_scale;
p2.y = p1.y;
IDF_SEGMENT* seg = new IDF_SEGMENT( p1, p2, 360, true );
- if( !seg )
- {
- std::cerr << "* FAULT: could not add a linear segment to the outline\n";
- }
- else
- {
+ if( seg )
lines.push_back( seg );
- }
return;
}
@@ -109,8 +100,8 @@
{
IDF_POINT p1, p2;
- p1.x = data.basePoint.x;
- p1.y = data.basePoint.y;
+ p1.x = data.basePoint.x * m_scale;
+ p1.y = data.basePoint.y * m_scale;
// note: DXF circles always run CCW
double ea = data.endangle;
@@ -118,21 +109,15 @@
while( ea < data.staangle )
ea += M_PI;
- p2.x = p1.x + cos( data.staangle ) * data.radious;
- p2.y = p1.y + sin( data.staangle ) * data.radious;
+ p2.x = p1.x + cos( data.staangle ) * data.radious * m_scale;
+ p2.y = p1.y + sin( data.staangle ) * data.radious * m_scale;
double angle = ( ea - data.staangle ) * 180.0 / M_PI;
IDF_SEGMENT* seg = new IDF_SEGMENT( p1, p2, angle, true );
- if( !seg )
- {
- std::cerr << "* FAULT: could not add a linear segment to the outline\n";
- }
- else
- {
+ if( seg )
lines.push_back( seg );
- }
return;
}
@@ -290,3 +275,186 @@
return true;
}
+
+
+void DXF2IDF::addHeader( const DRW_Header* data )
+{
+ std::map<std::string, DRW_Variant*>::const_iterator it;
+ m_scale = 1.0; // assume no scale factor
+
+ for( it = data->vars.begin(); it != data->vars.end(); ++it )
+ {
+ std::string key = ( (*it).first ).c_str();
+
+ if( key == "$INSUNITS" )
+ {
+ DRW_Variant* var = (*it).second;
+
+ switch( var->content.i )
+ {
+ case 1: // inches
+ m_scale = 25.4;
+ break;
+
+ case 2: // feet
+ m_scale = 304.8;
+ break;
+
+ case 5: // centimeters
+ m_scale = 10.0;
+ break;
+
+ case 6: // meters
+ m_scale = 1000.0;
+ break;
+
+ case 8: // microinches
+ m_scale = 2.54e-5;
+ break;
+
+ case 9: // mils
+ m_scale = 0.0254;
+ break;
+
+ case 10: // yards
+ m_scale = 914.4;
+ break;
+
+ case 11: // Angstroms
+ m_scale = 1.0e-7;
+ break;
+
+ case 12: // nanometers
+ m_scale = 1.0e-6;
+ break;
+
+ case 13: // micrometers
+ m_scale = 1.0e-3;
+ break;
+
+ case 14: // decimeters
+ m_scale = 100.0;
+ break;
+
+ default:
+ // use the default of 1.0 for:
+ // 0: Unspecified Units
+ // 4: mm
+ // 3: miles
+ // 7: kilometers
+ // 15: decameters
+ // 16: hectometers
+ // 17: gigameters
+ // 18: AU
+ // 19: lightyears
+ // 20: parsecs
+ break;
+ }
+ }
+ }
+}
+
+
+void DXF2IDF::addLWPolyline(const DRW_LWPolyline& data )
+{
+ IDF_POINT poly_start;
+ IDF_POINT seg_start;
+ IDF_POINT seg_end;
+ double bulge = 0.0;
+
+ if( !data.vertlist.empty() )
+ {
+ DRW_Vertex2D* vertex = data.vertlist[0];
+ seg_start.x = vertex->x * m_scale;
+ seg_start.y = vertex->y * m_scale;
+ poly_start = seg_start;
+ bulge = vertex->bulge;
+ }
+
+ for( size_t i = 1; i < data.vertlist.size(); ++i )
+ {
+ DRW_Vertex2D* vertex = data.vertlist[i];
+ seg_end.x = vertex->x * m_scale;
+ seg_end.y = vertex->y * m_scale;
+
+ if( std::abs( bulge ) < MIN_BULGE )
+ insertLine( seg_start, seg_end );
+ else
+ insertArc( seg_start, seg_end, bulge );
+
+ seg_start = seg_end;
+ bulge = vertex->bulge;
+ }
+
+ // Polyline flags bit 0 indicates closed (1) or open (0) polyline
+ if( data.flags & 1 )
+ {
+ if( std::abs( bulge ) < MIN_BULGE )
+ insertLine( seg_start, poly_start );
+ else
+ insertArc( seg_start, poly_start, bulge );
+ }
+
+ return;
+}
+
+
+void DXF2IDF::addPolyline(const DRW_Polyline& data )
+{
+ IDF_POINT poly_start;
+ IDF_POINT seg_start;
+ IDF_POINT seg_end;
+
+ if( !data.vertlist.empty() )
+ {
+ DRW_Vertex* vertex = data.vertlist[0];
+ seg_start.x = vertex->basePoint.x * m_scale;
+ seg_start.y = vertex->basePoint.y * m_scale;
+ poly_start = seg_start;
+ }
+
+ for( size_t i = 1; i < data.vertlist.size(); ++i )
+ {
+ DRW_Vertex* vertex = data.vertlist[i];
+ seg_end.x = vertex->basePoint.x * m_scale;
+ seg_end.y = vertex->basePoint.y * m_scale;
+ insertLine( seg_start, seg_end );
+ seg_start = seg_end;
+ }
+
+ // Polyline flags bit 0 indicates closed (1) or open (0) polyline
+ if( data.flags & 1 )
+ insertLine( seg_start, poly_start );
+
+ return;
+}
+
+
+void DXF2IDF::insertLine( const IDF_POINT& aSegStart, const IDF_POINT& aSegEnd )
+{
+ IDF_SEGMENT* seg = new IDF_SEGMENT( aSegStart, aSegEnd );
+
+ if( seg )
+ lines.push_back( seg );
+
+ return;
+}
+
+
+void DXF2IDF::insertArc( const IDF_POINT& aSegStart, const IDF_POINT& aSegEnd,
+ double aBulge )
+{
+ if( aBulge < -MAX_BULGE )
+ aBulge = -MAX_BULGE;
+ else if( aBulge > MAX_BULGE )
+ aBulge = MAX_BULGE;
+
+ double ang = 720.0 * atan( aBulge ) / M_PI;
+
+ IDF_SEGMENT* seg = new IDF_SEGMENT( aSegStart, aSegEnd, ang, false );
+
+ if( seg )
+ lines.push_back( seg );
+
+ return;
+}
=== modified file 'utils/idftools/dxf2idf.h'
--- utils/idftools/dxf2idf.h 2015-02-24 09:07:40 +0000
+++ utils/idftools/dxf2idf.h 2016-03-21 10:15:55 +0000
@@ -32,6 +32,10 @@
{
private:
std::list< IDF_SEGMENT* > lines; // Unsorted list of graphical segments
+ double m_scale; // scaling factor to mm
+
+ void insertLine( const IDF_POINT& aSegStart, const IDF_POINT& aSegEnd );
+ void insertArc( const IDF_POINT& aSegStart, const IDF_POINT& aSegEnd, double aBulge );
public:
~DXF2IDF();
@@ -41,12 +45,14 @@
private:
// DRW_Interface implemented callback functions
+ virtual void addHeader( const DRW_Header* data );
virtual void addLine(const DRW_Line& data);
virtual void addArc(const DRW_Arc& data );
virtual void addCircle(const DRW_Circle& data );
+ virtual void addLWPolyline(const DRW_LWPolyline& data );
+ virtual void addPolyline(const DRW_Polyline& data );
// DRW_Interface callbacks unsupported by DXF2IDF
- virtual void addHeader( const DRW_Header* data ){}
virtual void addLType( const DRW_LType& data ){}
virtual void addLayer( const DRW_Layer& data ){}
virtual void addDimStyle( const DRW_Dimstyle& data ){}
@@ -59,8 +65,6 @@
virtual void addRay(const DRW_Ray& data ){}
virtual void addXline(const DRW_Xline& data ){}
virtual void addEllipse(const DRW_Ellipse& data ){}
- virtual void addLWPolyline(const DRW_LWPolyline& data ){}
- virtual void addPolyline(const DRW_Polyline& data ){}
virtual void addSpline(const DRW_Spline* data ){}
virtual void addKnot(const DRW_Entity&){}
virtual void addInsert(const DRW_Insert& data ){}
=== modified file 'utils/idftools/idf_common.cpp'
--- utils/idftools/idf_common.cpp 2015-07-03 08:42:47 +0000
+++ utils/idftools/idf_common.cpp 2016-03-21 10:31:06 +0000
@@ -1141,8 +1141,10 @@
else
offAng -= M_PI_2;
- if( ( angle > 180.0 ) || ( angle < -180.0 ) )
+ if( angle < -180.0 )
offAng += M_PI;
+ else if( angle > 180 )
+ offAng -= M_PI;
center.x = h * cos( offAng ) + xm;
center.y = h * sin( offAng ) + ym;
Follow ups