|
|
@ -2,6 +2,7 @@ |
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application. |
|
|
|
* |
|
|
|
* Copyright (C) 2014 Cirilo Bernardo |
|
|
|
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors. |
|
|
|
* |
|
|
|
* This program is free software; you can redistribute it and/or |
|
|
|
* modify it under the terms of the GNU General Public License |
|
|
@ -23,7 +24,6 @@ |
|
|
|
|
|
|
|
#include <cstdio>
|
|
|
|
#include <iostream>
|
|
|
|
#include <libdxfrw.h>
|
|
|
|
#include <dxf2idf.h>
|
|
|
|
|
|
|
|
// differences in angle smaller than MIN_ANG are considered equal
|
|
|
@ -51,40 +51,38 @@ DXF2IDF::~DXF2IDF() |
|
|
|
|
|
|
|
bool DXF2IDF::ReadDxf( const std::string& aFile ) |
|
|
|
{ |
|
|
|
dxfRW* reader = new dxfRW( aFile.c_str() ); |
|
|
|
DL_Dxf dxf_reader; |
|
|
|
bool success = true; |
|
|
|
|
|
|
|
if( !reader ) |
|
|
|
return false; |
|
|
|
|
|
|
|
bool success = reader->read( this, true ); |
|
|
|
if( !dxf_reader.in( aFile, this ) ) // if file open failed
|
|
|
|
success = false; |
|
|
|
|
|
|
|
delete reader; |
|
|
|
return success; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void DXF2IDF::addLine( const DRW_Line& data ) |
|
|
|
void DXF2IDF::addLine( const DL_LineData& aData ) |
|
|
|
{ |
|
|
|
IDF_POINT p1, p2; |
|
|
|
|
|
|
|
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; |
|
|
|
p1.x = aData.x1 * m_scale; |
|
|
|
p1.y = aData.y1 * m_scale; |
|
|
|
p2.x = aData.x2 * m_scale; |
|
|
|
p2.y = aData.y2 * m_scale; |
|
|
|
|
|
|
|
insertLine( p1, p2 ); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void DXF2IDF::addCircle( const DRW_Circle& data ) |
|
|
|
void DXF2IDF::addCircle( const DL_CircleData& aData ) |
|
|
|
{ |
|
|
|
IDF_POINT p1, p2; |
|
|
|
|
|
|
|
p1.x = data.basePoint.x * m_scale; |
|
|
|
p1.y = data.basePoint.y * m_scale; |
|
|
|
p1.x = aData.cx * m_scale; |
|
|
|
p1.y = aData.cy * m_scale; |
|
|
|
|
|
|
|
p2.x = p1.x + data.radious * m_scale; |
|
|
|
p2.x = p1.x + aData.radius * m_scale; |
|
|
|
p2.y = p1.y; |
|
|
|
|
|
|
|
IDF_SEGMENT* seg = new IDF_SEGMENT( p1, p2, 360, true ); |
|
|
@ -96,23 +94,23 @@ void DXF2IDF::addCircle( const DRW_Circle& data ) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void DXF2IDF::addArc( const DRW_Arc& data ) |
|
|
|
void DXF2IDF::addArc( const DL_ArcData& aData ) |
|
|
|
{ |
|
|
|
IDF_POINT p1, p2; |
|
|
|
|
|
|
|
p1.x = data.basePoint.x * m_scale; |
|
|
|
p1.y = data.basePoint.y * m_scale; |
|
|
|
p1.x = aData.cx * m_scale; |
|
|
|
p1.y = aData.cy * m_scale; |
|
|
|
|
|
|
|
// note: DXF circles always run CCW
|
|
|
|
double ea = data.endangle; |
|
|
|
double ea = aData.angle2; |
|
|
|
|
|
|
|
while( ea < data.staangle ) |
|
|
|
while( ea < aData.angle1 ) |
|
|
|
ea += M_PI; |
|
|
|
|
|
|
|
p2.x = p1.x + cos( data.staangle ) * data.radious * m_scale; |
|
|
|
p2.y = p1.y + sin( data.staangle ) * data.radious * m_scale; |
|
|
|
p2.x = p1.x + cos( aData.angle1 ) * aData.radius * m_scale; |
|
|
|
p2.y = p1.y + sin( aData.angle1 ) * aData.radius * m_scale; |
|
|
|
|
|
|
|
double angle = ( ea - data.staangle ) * 180.0 / M_PI; |
|
|
|
double angle = ( ea - aData.angle1 ) * 180.0 / M_PI; |
|
|
|
|
|
|
|
IDF_SEGMENT* seg = new IDF_SEGMENT( p1, p2, angle, true ); |
|
|
|
|
|
|
@ -276,159 +274,141 @@ bool DXF2IDF::WriteOutline( FILE* aFile, bool isInch ) |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void DXF2IDF::addHeader( const DRW_Header* data ) |
|
|
|
void DXF2IDF::setVariableInt( const std::string& key, int value, int code ) |
|
|
|
{ |
|
|
|
std::map<std::string, DRW_Variant*>::const_iterator it; |
|
|
|
// Called for every int variable in the DXF file (e.g. "$INSUNITS").
|
|
|
|
|
|
|
|
for( it = data->vars.begin(); it != data->vars.end(); ++it ) |
|
|
|
if( key == "$INSUNITS" ) // Drawing units
|
|
|
|
{ |
|
|
|
std::string key = ( (*it).first ).c_str(); |
|
|
|
|
|
|
|
if( key == "$INSUNITS" ) |
|
|
|
switch( value ) |
|
|
|
{ |
|
|
|
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; |
|
|
|
} |
|
|
|
case 1: // inches
|
|
|
|
m_scale = 25.4; |
|
|
|
break; |
|
|
|
|
|
|
|
case 2: // feet
|
|
|
|
m_scale = 304.8; |
|
|
|
break; |
|
|
|
|
|
|
|
case 4: // mm
|
|
|
|
m_scale = 1.0; |
|
|
|
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
|
|
|
|
// 3: miles
|
|
|
|
// 7: kilometers
|
|
|
|
// 15: decameters
|
|
|
|
// 16: hectometers
|
|
|
|
// 17: gigameters
|
|
|
|
// 18: AU
|
|
|
|
// 19: lightyears
|
|
|
|
// 20: parsecs
|
|
|
|
m_scale = 1.0; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void DXF2IDF::addLWPolyline(const DRW_LWPolyline& data ) |
|
|
|
void DXF2IDF::addPolyline(const DL_PolylineData& aData ) |
|
|
|
{ |
|
|
|
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; |
|
|
|
// Convert DXF Polylines into a series of Lines and Arcs.
|
|
|
|
// A Polyline (as opposed to a LWPolyline) may be a 3D line or
|
|
|
|
// even a 3D Mesh. The only type of Polyline which is guaranteed
|
|
|
|
// to import correctly is a 2D Polyline in X and Y, which is what
|
|
|
|
// we assume of all Polylines. The width used is the width of the Polyline.
|
|
|
|
// per-vertex line widths, if present, are ignored.
|
|
|
|
m_entityParseStatus = 1; |
|
|
|
m_entity_flags = aData.flags; |
|
|
|
m_entityType = DL_ENTITY_POLYLINE; |
|
|
|
} |
|
|
|
|
|
|
|
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; |
|
|
|
} |
|
|
|
void DXF2IDF::addVertex( const DL_VertexData& aData ) |
|
|
|
{ |
|
|
|
if( m_entityParseStatus == 0 ) |
|
|
|
return; // Error
|
|
|
|
|
|
|
|
// Polyline flags bit 0 indicates closed (1) or open (0) polyline
|
|
|
|
if( data.flags & 1 ) |
|
|
|
if( m_entityParseStatus == 1 ) // This is the first vertex of an entity
|
|
|
|
{ |
|
|
|
if( std::abs( bulge ) < MIN_BULGE ) |
|
|
|
insertLine( seg_start, poly_start ); |
|
|
|
else |
|
|
|
insertArc( seg_start, poly_start, bulge ); |
|
|
|
m_lastCoordinate.x = aData.x * m_scale; |
|
|
|
m_lastCoordinate.y = aData.y * m_scale; |
|
|
|
m_polylineStart = m_lastCoordinate; |
|
|
|
m_bulgeVertex = aData.bulge; |
|
|
|
m_entityParseStatus = 2; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
return; |
|
|
|
IDF_POINT seg_end; |
|
|
|
|
|
|
|
seg_end.x = aData.x * m_scale; |
|
|
|
seg_end.y = aData.y * m_scale; |
|
|
|
insertLine( m_lastCoordinate, seg_end ); |
|
|
|
m_lastCoordinate = seg_end; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void DXF2IDF::addPolyline(const DRW_Polyline& data ) |
|
|
|
void DXF2IDF::endEntity() |
|
|
|
{ |
|
|
|
IDF_POINT poly_start; |
|
|
|
IDF_POINT seg_start; |
|
|
|
IDF_POINT seg_end; |
|
|
|
|
|
|
|
if( !data.vertlist.empty() ) |
|
|
|
if( m_entityType == DL_ENTITY_POLYLINE ) |
|
|
|
{ |
|
|
|
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( m_entity_flags & 1 ) |
|
|
|
{ |
|
|
|
if( std::abs( m_bulgeVertex ) < MIN_BULGE ) |
|
|
|
insertLine( m_lastCoordinate, m_polylineStart ); |
|
|
|
else |
|
|
|
insertArc( m_lastCoordinate, m_polylineStart, m_bulgeVertex ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Polyline flags bit 0 indicates closed (1) or open (0) polyline
|
|
|
|
if( data.flags & 1 ) |
|
|
|
insertLine( seg_start, poly_start ); |
|
|
|
|
|
|
|
return; |
|
|
|
m_entityType = 0 ; |
|
|
|
m_entity_flags = 0; |
|
|
|
m_entityParseStatus = 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DXF2IDF::insertLine( const IDF_POINT& aSegStart, const IDF_POINT& aSegEnd ) |
|
|
|
{ |
|
|
|
IDF_SEGMENT* seg = new IDF_SEGMENT( aSegStart, aSegEnd ); |
|
|
|