84#define MIN_BULGE 0.0218
86#define SCALE_FACTOR(x) (x)
106 m_layers.push_back( std::move( layer0 ) );
123 catch(
const std::bad_alloc& )
131 ReportMsg(
_(
"Memory was exhausted trying to load the DXF, it may be too large." ) );
143 catch(
const std::bad_alloc& )
151 ReportMsg(
_(
"Memory was exhausted trying to load the DXF, it may be too large." ) );
220 FILE* fp = wxFopen( aFile, wxT(
"rt" ) );
226 bool success = dxf_reader.in( fp,
this );
236 std::string str(
reinterpret_cast<char*
>( aMemBuffer.GetData() ), aMemBuffer.GetDataLen() );
238 bool success = dxf_reader.in( str,
this );
274 m_curr_entity.m_SplineControlPointList.emplace_back( aData.x , aData.y, aData.w );
282 m_curr_entity.m_SplineFitPointList.emplace_back( aData.x, aData.y );
295 wxString
name = wxString::FromUTF8( aData.name.c_str() );
297 int lw = attributes.getWidth();
302 std::unique_ptr<DXF_IMPORT_LAYER> layer = std::make_unique<DXF_IMPORT_LAYER>(
name, lw );
304 m_layers.push_back( std::move( layer ) );
312 wxString description =
From_UTF8( data.description.c_str() );
335 wxString layerName = wxString::FromUTF8( aLayerName.c_str() );
337 if( !layerName.IsEmpty() )
340 [layerName](
const auto& it )
342 return it->m_layerName == layerName;
346 layer = resultIt->get();
355 wxString layerName = wxString::FromUTF8( aLayerName.c_str() );
357 if( layerName.IsEmpty() )
358 layerName = wxS(
"0" );
367 wxString blockName = wxString::FromUTF8( aBlockName.c_str() );
369 if( !blockName.IsEmpty() )
372 [blockName](
const auto& it )
374 return it->m_name == blockName;
378 block = resultIt->get();
388 wxString styleName = wxString::FromUTF8( aStyleName.c_str() );
390 if( !styleName.IsEmpty() )
393 [styleName](
const auto& it )
395 return it->m_name == styleName;
399 style = resultIt->get();
418 bufferToUse->
AddLine( start,
end, lineWidth );
451 if( aData.startWidth > 0.0 )
452 lineWidth = aData.startWidth / 100.0;
453 else if ( aData.endWidth > 0.0 )
454 lineWidth = aData.endWidth / 100.0;
456 const DL_VertexData* vertex = &aData;
517 wxString
name = wxString::FromUTF8( aData.name.c_str() );
519 std::unique_ptr<DXF_IMPORT_BLOCK> block = std::make_unique<DXF_IMPORT_BLOCK>(
name, aData.bpx,
522 m_blocks.push_back( std::move( block ) );
537 if( block ==
nullptr )
556 for(
const std::unique_ptr<IMPORTED_SHAPE>& shape : block->
m_buffer.
GetShapes() )
558 std::unique_ptr<IMPORTED_SHAPE> newShape = shape->clone();
560 newShape->Transform( trans, translation );
562 if( newShape->GetSourceLayer().IsEmpty() || newShape->GetSourceLayer() == wxS(
"0" ) )
563 newShape->SetSourceLayer( insertLayer );
608 std::swap( startangle, endangle );
612 VECTOR2D startPoint( aData.radius, 0.0 );
615 mapY( startPoint.
y + centerCoords.
y ) );
618 EDA_ANGLE angle = -( endangle - startangle );
630 bufferToUse->
AddArc(
center, arcStart, angle, lineWidth );
661 if( startAngle > endAngle )
664 if( aData.ratio == 1.0 )
668 if( startAngle == endAngle )
670 DL_CircleData
circle( aData.cx, aData.cy, aData.cz,
radius );
680 DL_ArcData arc( aData.cx, aData.cy, aData.cz,
radius, startAngle.
AsDegrees(),
698 double minorRadius = majorRadius * aData.ratio;
701 if( startAngle == endAngle ||
std::abs( ( endAngle - startAngle ).AsDegrees() - 360.0 ) < 1e-9 )
703 bufferToUse->
AddEllipse(
center, majorRadius, minorRadius, rotation, lineWidth,
false );
707 bufferToUse->
AddEllipseArc(
center, majorRadius, minorRadius, rotation, startAngle, endAngle, lineWidth );
722 std::isnan( aData.apy ) ? 0 : aData.apy,
723 std::isnan( aData.apz ) ? 0 : aData.apz ) );
728 if( aData.vJustification != 0 || aData.hJustification != 0 || aData.hJustification == 4 )
730 if( aData.hJustification != 3 && aData.hJustification != 5 )
742 double textHeight =
mapDim( aData.height );
745 double charWidth = textHeight * 0.9;
747 if( style !=
nullptr )
750 double textWidth = charWidth *
text.length();
751 double textThickness = textHeight / 8.0;
761 switch( aData.vJustification )
767 topLeft.
y = textHeight;
768 topRight.
y = textHeight;
774 bottomRight.
y = -textHeight / 2.0;
775 bottomLeft.
y = -textHeight / 2.0;
776 topLeft.
y = textHeight / 2.0;
777 topRight.
y = textHeight / 2.0;
783 bottomLeft.
y = -textHeight;
784 bottomRight.
y = -textHeight;
788 switch( aData.hJustification )
795 bottomRight.
x = textWidth;
796 topRight.
x = textWidth;
803 bottomLeft.
x = -textWidth / 2.0;
804 topLeft.
x = -textWidth / 2.0;
805 bottomRight.
x = textWidth / 2.0;
806 topRight.
x = textWidth / 2.0;
812 bottomLeft.
x = -textWidth;
813 topLeft.
x = -textWidth;
818 wxString sty = wxString::FromUTF8( aData.style.c_str() );
821 if( aData.textgen == 2 )
824 }
else if( aData.textgen == 4 )
834 double angle_degree = aData.angle * 180 /
M_PI;
838 double angleInRads = angle_degree *
M_PI / 180.0;
839 double cosine = cos(angleInRads);
840 double sine = sin(angleInRads);
845 bufferToUse->
AddText( refPoint,
text, textHeight, charWidth, textThickness, angle_degree,
846 hJustify, vJustify );
849 bottomLeft.
x = bottomLeft.
x * cosine - bottomLeft.
y * sine;
850 bottomLeft.
y = bottomLeft.
x * sine + bottomLeft.
y * cosine;
852 bottomRight.
x = bottomRight.
x * cosine - bottomRight.
y * sine;
853 bottomRight.
y = bottomRight.
x * sine + bottomRight.
y * cosine;
855 topLeft.
x = topLeft.
x * cosine - topLeft.
y * sine;
856 topLeft.
y = topLeft.
x * sine + topLeft.
y * cosine;
858 topRight.
x = topRight.
x * cosine - topRight.
y * sine;
859 topRight.
y = topRight.
x * sine + topRight.
y * cosine;
861 bottomLeft += refPoint;
862 bottomRight += refPoint;
864 topRight += refPoint;
891 double textHeight =
mapDim( aData.height );
894 double charWidth = textHeight * 0.9;
896 if( style !=
nullptr )
899 double textWidth = charWidth *
text.length();
900 double textThickness = textHeight/8.0;
915 if( aData.attachmentPoint <= 3 )
919 bottomLeft.
y = -textHeight;
920 bottomRight.
y = -textHeight;
922 else if( aData.attachmentPoint <= 6 )
926 bottomRight.
y = -textHeight / 2.0;
927 bottomLeft.
y = -textHeight / 2.0;
928 topLeft.
y = textHeight / 2.0;
929 topRight.
y = textHeight / 2.0;
935 topLeft.
y = textHeight;
936 topRight.
y = textHeight;
939 if( aData.attachmentPoint % 3 == 1 )
943 bottomRight.
x = textWidth;
944 topRight.
x = textWidth;
946 else if( aData.attachmentPoint % 3 == 2 )
950 bottomLeft.
x = -textWidth / 2.0;
951 topLeft.
x = -textWidth / 2.0;
952 bottomRight.
x = textWidth / 2.0;
953 topRight.
x = textWidth / 2.0;
959 bottomLeft.
x = -textWidth;
960 topLeft.
x = -textWidth;
964 if( data.alignH == 1 )
968 else if( data.alignH == 3 )
977 if( aData.alignV == 1 )
989 double angle_degree = aData.angle * 180/
M_PI;
993 double angleInRads = angle_degree *
M_PI / 180.0;
994 double cosine = cos(angleInRads);
995 double sine = sin(angleInRads);
1001 bufferToUse->
AddText( textpos,
text, textHeight, charWidth, textThickness, angle_degree,
1002 hJustify, vJustify );
1004 bottomLeft.
x = bottomLeft.
x * cosine - bottomLeft.
y * sine;
1005 bottomLeft.
y = bottomLeft.
x * sine + bottomLeft.
y * cosine;
1007 bottomRight.
x = bottomRight.
x * cosine - bottomRight.
y * sine;
1008 bottomRight.
y = bottomRight.
x * sine + bottomRight.
y * cosine;
1010 topLeft.
x = topLeft.
x * cosine - topLeft.
y * sine;
1011 topLeft.
y = topLeft.
x * sine + topLeft.
y * cosine;
1013 topRight.
x = topRight.
x * cosine - topRight.
y * sine;
1014 topRight.
y = topRight.
x * sine + topRight.
y * cosine;
1016 bottomLeft += textpos;
1017 bottomRight += textpos;
1019 topRight += textpos;
1080 wxArrayString names;
1083 names.Add( choice.second );
1093 if( aSelection < 0 || aSelection >= (
int) choices.size() )
1096 return choices[aSelection].first;
1104 if( key ==
"$DWGCODEPAGE" )
1110 if( key ==
"$AUPREC" )
1116 if( key ==
"$LUPREC" )
1122 if( key ==
"$INSUNITS" )
1172 for(
unsigned i = 0; i<aStr.length(); ++i )
1176 if( c > 175 || c < 11 )
1178 res.append( aStr.Mid( j, i - j ) );
1184 res += wxT(
"\\P" );
1194 res += wxT(
"%%C" );
1199 res += wxT(
"%%D" );
1204 res += wxT(
"%%P" );
1216 res.append( aStr.Mid( j ) );
1226 int overbarLevel = -1;
1232 for( i = 0; i < aData.length(); i++ )
1234 switch( (
wchar_t) aData[i] )
1241 if( overbarLevel == braces )
1250 if( ++i >= aData.length() )
1253 switch( (
wchar_t) aData[i] )
1255 case 'I':
res <<
'\t';
break;
1256 case 'J':
res <<
'\b';
break;
1257 case ' ':
res <<
'^';
break;
1264 if( ++i >= aData.length() )
1267 switch( (
wchar_t) aData[i] )
1283 for( ; codeHex.length() < 4 && i < aData.length(); i++ )
1284 codeHex << aData[i];
1286 unsigned long codeVal = 0;
1288 if( codeHex.ToCULong( &codeVal, 16 ) && codeVal != 0 )
1289 res << wxUniChar( codeVal );
1300 for( ; i < aData.length(); i++ )
1302 if( aData[i] ==
';' )
1305 stacked << aData[i];
1308 if( stacked.Contains( wxS(
"#" ) ) )
1311 res << stacked.BeforeFirst(
'#' );
1312 res <<
'}' <<
'/' <<
'_' <<
'{';
1313 res << stacked.AfterFirst(
'#' );
1318 stacked.Replace( wxS(
"^ " ), wxS(
"/" ) );
1325 if( overbarLevel == -1 )
1328 overbarLevel = braces;
1332 if( overbarLevel == braces )
1358 for( ; i < aData.length(); i++ )
1360 if( aData[i] ==
';' )
1366 if( ++i >= aData.length() )
1375 default:
res << aData[i];
1379 if( overbarLevel != -1 )
1389 regexp.Compile( wxT(
"%%[cC]" ) );
1392 regexp.Replace( &
res, wxChar( 0xD8 ) );
1395 regexp.Replace( &
res, wxChar( 0x2205 ) );
1399 regexp.Compile( wxT(
"%%[dD]" ) );
1400 regexp.Replace( &
res, wxChar( 0x00B0 ) );
1403 regexp.Compile( wxT(
"%%[pP]" ) );
1404 regexp.Replace( &
res, wxChar( 0x00B1 ) );
1413 wxString
name = wxString::FromUTF8( aData.name.c_str() );
1415 auto style = std::make_unique<DXF_IMPORT_STYLE>(
name, aData.fixedTextHeight, aData.widthFactor,
1416 aData.bold, aData.italic );
1418 m_styles.push_back( std::move( style ) );
1432 double lineWidth = 0.0001;
1433 double thickness =
mapDim( std::max( aData.thickness, 0.01 ) );
1448 const VECTOR2D& aSegEnd,
double aWidth )
1464 double aBulge,
double aWidth )
1470 if( aBulge < -2000.0 )
1472 else if( aBulge > 2000.0 )
1475 double ang = 4.0 * atan( aBulge );
1482 double offAng = atan2( ep.
y - sp.
y, ep.
x - sp.
x );
1485 double d = 0.5 * sqrt( ( sp.
x - ep.
x ) * ( sp.
x - ep.
x ) + ( sp.
y - ep.
y ) * ( sp.
y - ep.
y ) );
1488 double xm = ( sp.
x + ep.
x ) * 0.5;
1489 double ym = ( sp.
y + ep.
y ) * 0.5;
1490 double radius = d / sin( ang * 0.5 );
1502 double h = sqrt( dh2 );
1514 else if( ang >
M_PI )
1518 double cx = h * cos( offAng ) + xm;
1519 double cy = h * sin( offAng ) + ym;
1537 bufferToUse->
AddArc(
center, arc_start, angle, aWidth );
1546#include "tinysplinecxx.h"
1551 wxLogMessage(
"spl deg %d kn %d ctr %d fit %d",
1558 unsigned imax =
m_curr_entity.m_SplineControlPointList.size();
1567 for(
unsigned int ii = 1; ii < imax; ++ii )
1572 if( startpoint != endpoint )
1579 startpoint = endpoint;
1583 std::vector<double> ctrlp;
1585 for(
unsigned ii = 0; ii < imax; ++ii )
1587 ctrlp.push_back(
m_curr_entity.m_SplineControlPointList[ii].m_x );
1588 ctrlp.push_back(
m_curr_entity.m_SplineControlPointList[ii].m_y );
1591 tinyspline::BSpline beziers;
1592 std::vector<double> coords;
1596 tinyspline::BSpline dxfspline(
m_curr_entity.m_SplineControlPointList.size(),
1599 dxfspline.setControlPoints( ctrlp );
1602 if( dxfspline.degree() < 3 )
1603 dxfspline = dxfspline.elevateDegree( 3 - dxfspline.degree() );
1605 beziers = dxfspline.toBeziers();
1606 coords = beziers.controlPoints();
1608 catch(
const std::runtime_error& )
1612 ReportMsg(
_(
"Invalid spline definition encountered" ) );
1616 size_t order = beziers.order();
1617 size_t dim = beziers.dimension();
1618 size_t numBeziers = ( coords.size() / dim ) / order;
1620 for(
size_t i = 0; i < numBeziers; i++ )
1622 size_t ii = i * dim * order;
1629 if( ii + 5 >= coords.size() )
1630 bezierControl2 = bezierControl1;
1632 bezierControl2 =
VECTOR2D(
mapX( coords[ii + 4] ),
mapY( coords[ii + 5] ) );
1636 if( ii + 7 >= coords.size() )
1637 end = bezierControl2;
1644 bufferToUse->
AddSpline( start, bezierControl1, bezierControl2,
end, aWidth );
1664 double direction[3];
1665 aData->getDirection( direction );
1669 if( ( abs( arbZ.
x ) < ( 1.0 / 64.0 ) ) && ( abs( arbZ.
y ) < ( 1.0 / 64.0 ) ) )
1682 return arbitraryAxis * point;
1692 MATRIX3x3 world( worldX, worldY, worldZ );
1694 return world * point;
constexpr void SetOrigin(const Vec &pos)
constexpr void SetEnd(coord_type x, coord_type y)
A helper class to hold layer settings temporarily during import.
GRAPHICS_IMPORTER_BUFFER m_buffer
A helper class to hold layer settings temporarily during import.
DXF_IMPORT_UNITS m_currentUnit
virtual void addPolyline(const DL_PolylineData &aData) override
double mapY(double aDxfCoordY)
std::vector< std::unique_ptr< DXF_IMPORT_LAYER > > m_layers
void addEllipse(const DL_EllipseData &aData) override
static wxString toNativeString(const wxString &aData)
Convert a DXF encoded string into a native Unicode string.
virtual void setVariableInt(const std::string &key, int value, int code) override
Called for every int variable in the DXF file (e.g.
bool LoadFromMemory(const wxMemoryBuffer &aMemBuffer) override
Set memory buffer with content for import.
void insertSpline(double aWidth)
virtual void addLine(const DL_LineData &aData) override
VECTOR3D ocsToWcs(const MATRIX3x3D &arbitraryAxis, VECTOR3D point)
Convert a given object coordinate point to world coordinate using the given arbitrary axis vectors.
void insertLine(const VECTOR2D &aSegStart, const VECTOR2D &aSegEnd, double aWidth)
DXF_IMPORT_BLOCK * getImportBlock(const std::string &aBlockName)
Return the import layer block.
double getCurrentUnitScale()
virtual void addBlock(const DL_BlockData &) override
Called for each BLOCK in the DXF file.
virtual void addLayer(const DL_LayerData &aData) override
virtual void addCircle(const DL_CircleData &aData) override
virtual void addMText(const DL_MTextData &aData) override
DXF_IMPORT_LAYER * getImportLayer(const std::string &aLayerName)
Return the import layer data.
static wxString toDxfString(const wxString &aStr)
Convert a native Unicode string into a DXF encoded string.
DXF_IMPORT_STYLE * getImportStyle(const std::string &aStyleName)
Return the import style.
virtual void addInsert(const DL_InsertData &aData) override
std::string m_mtextContent
BOX2D GetImageBBox() const override
Return image bounding box from original imported file.
MATRIX3x3D getArbitraryAxis(DL_Extrusion *aData)
double GetImageWidth() const override
Return image width from original imported file.
double GetImageHeight() const override
Return image height from original imported file.
void updateImageLimits(const VECTOR2D &aPoint)
virtual void addTextStyle(const DL_StyleData &aData) override
virtual void addVertex(const DL_VertexData &aData) override
Called for every polyline vertex.
VECTOR3D wcsToOcs(const MATRIX3x3D &arbitraryAxis, VECTOR3D point)
Convert a given world coordinate point to object coordinate using the given arbitrary axis vectors.
virtual void addSpline(const DL_SplineData &aData) override
Called for every spline.
virtual void addText(const DL_TextData &aData) override
virtual void endBlock() override
virtual void setVariableString(const std::string &key, const std::string &value, int code) override
Called for every string variable in the DXF file (e.g.
virtual void addKnot(const DL_KnotData &aData) override
Called for every spline knot value.
bool ImportDxfFile(const wxString &aFile)
Implementation of the method used for communicate with this filter.
virtual void addArc(const DL_ArcData &aData) override
void SetDefaultLineWidthMM(double aWidth)
Set the default line width when importing dxf items like lines to Pcbnew.
virtual void addFitPoint(const DL_FitPointData &aData) override
Called for every spline fit point.
virtual void addPoint(const DL_PointData &aData) override
double mapDim(double aDxfValue)
void ReportMsg(const wxString &aMessage) override
int m_importCoordinatePrecision
double mapX(double aDxfCoordX)
double lineWeightToWidth(int lw, DXF_IMPORT_LAYER *aLayer)
void insertArc(const VECTOR2D &aSegStart, const VECTOR2D &aSegEnd, double aBulge, double aWidth)
std::vector< std::unique_ptr< DXF_IMPORT_BLOCK > > m_blocks
bool Import() override
Actually imports the file.
virtual void addMTextChunk(const std::string &text) override
int m_importAnglePrecision
virtual void endEntity() override
virtual void addControlPoint(const DL_ControlPointData &aData) override
Called for every spline control point.
double m_defaultThickness
GRAPHICS_IMPORTER_BUFFER m_internalImporter
std::vector< std::unique_ptr< DXF_IMPORT_STYLE > > m_styles
bool Load(const wxString &aFileName) override
Load file for import.
DXF_IMPORT_BLOCK * m_currentBlock
DXF2BRD_ENTITY_DATA m_curr_entity
wxString getDxfLayerName(const std::string &aLayerName) const
virtual void SetImporter(GRAPHICS_IMPORTER *aImporter) override
Set the receiver of the imported shapes.
virtual void addLinetype(const DL_LinetypeData &data) override
A helper class to hold style settings temporarily during import.
std::list< std::unique_ptr< IMPORTED_SHAPE > > & GetShapes()
void AddCircle(const VECTOR2D &aCenter, double aRadius, const IMPORTED_STROKE &aStroke, bool aFilled, const COLOR4D &aFillColor=COLOR4D::UNSPECIFIED) override
Create an object representing a circle.
void AddSpline(const VECTOR2D &aStart, const VECTOR2D &aBezierControl1, const VECTOR2D &aBezierControl2, const VECTOR2D &aEnd, const IMPORTED_STROKE &aStroke) override
Create an object representing an arc.
void AddLine(const VECTOR2D &aStart, const VECTOR2D &aEnd, const IMPORTED_STROKE &aStroke) override
Create an object representing a line segment.
void AddEllipse(const VECTOR2D &aCenter, double aMajorRadius, double aMinorRadius, const EDA_ANGLE &aRotation, const IMPORTED_STROKE &aStroke, bool aFilled, const COLOR4D &aFillColor=COLOR4D::UNSPECIFIED) override
Create an object representing a closed ellipse.
void SetCurrentSourceLayer(const wxString &aSourceLayer) override
Set the source layer for the next buffered shape to be imported.
void AddArc(const VECTOR2D &aCenter, const VECTOR2D &aStart, const EDA_ANGLE &aAngle, const IMPORTED_STROKE &aStroke) override
Create an object representing an arc.
void AddText(const VECTOR2D &aOrigin, const wxString &aText, double aHeight, double aWidth, double aThickness, double aOrientation, GR_TEXT_H_ALIGN_T aHJustify, GR_TEXT_V_ALIGN_T aVJustify, const COLOR4D &aColor=COLOR4D::UNSPECIFIED) override
Create an object representing a text.
void AddEllipseArc(const VECTOR2D &aCenter, double aMajorRadius, double aMinorRadius, const EDA_ANGLE &aRotation, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle, const IMPORTED_STROKE &aStroke) override
Create an object representing an elliptical arc.
Interface that creates objects representing shapes for a given data model.
GRAPHICS_IMPORTER * m_importer
Importer used to create objects representing the imported shapes.
virtual void SetImporter(GRAPHICS_IMPORTER *aImporter)
Set the receiver of the imported shapes.
MATRIX3x3 describes a general 3x3 matrix.
void SetRotation(T aAngle)
Set the rotation components of the matrix.
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
VECTOR3< T > Normalize()
Compute the normalized vector.
VECTOR3< T > Cross(const VECTOR3< T > &aVector) const
Compute cross product of self with aVector.
wxArrayString GetDxfImportUnitChoices()
static std::vector< std::pair< DXF_IMPORT_UNITS, wxString > > dxfImportUnitChoices()
DXF_IMPORT_UNITS DxfImportUnitFromChoice(int aSelection)
#define DXF_IMPORT_LINEWEIGHT_BY_LW_DEFAULT
#define DXF_IMPORT_LINEWEIGHT_BY_LAYER
DXF_IMPORT_UNITS
DXF Units enum with values as specified in DXF 2012 Specification.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
This file contains miscellaneous commonly used macros and functions.
MATRIX3x3< double > MATRIX3x3D
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
wxString From_UTF8(const char *cstring)
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
double DEG2RAD(double deg)
VECTOR2< double > VECTOR2D
VECTOR3< double > VECTOR3D