44 const std::string& aMessage )
noexcept
49 ostr <<
"* " << aSourceFile <<
":";
51 ostr <<
"* [BUG: No Source File]:";
53 ostr << aSourceLine <<
":";
56 ostr << aSourceMethod <<
"(): ";
58 ostr <<
"[BUG: No Source Method]:\n* ";
96 while( !
FetchIDFLine( aBoardFile, iline, isComment, pos ) && aBoardFile.good() );
98 if( ( !aBoardFile.good() && !aBoardFile.eof() ) || iline.empty() )
101 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
"problems reading board notes" ) );
107 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
108 "invalid IDFv3 file\n"
109 "* Violation of specification: comment within a section (NOTES)" ) );
118 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
119 "invalid IDFv3 file\n"
120 "* Violation of specification: X position in NOTES section must not be "
135 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
136 "invalid IDFv3 file\n"
137 "* Violation of specification: X position in NOTES section is not "
144 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
145 "invalid IDFv3 file\n"
146 "* Violation of specification: Y position in NOTES section is "
153 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
154 "invalid IDFv3 file\n"
155 "* Violation of specification: Y position in NOTES section must not be "
167 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
168 "invalid IDFv3 file\n"
169 "* Violation of specification: Y position in NOTES section is not "
176 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
177 "invalid IDFv3 file\n"
178 "* Violation of specification: text height in NOTES section is "
185 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
186 "invalid IDFv3 file\n"
187 "* Violation of specification: text height in NOTES section must not "
199 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
200 "invalid IDFv3 file\n"
201 "* Violation of specification: text height in NOTES section is not "
208 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
209 "invalid IDFv3 file\n"
210 "* Violation of specification: text length in NOTES section is "
217 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
218 "invalid IDFv3 file\n"
219 "* Violation of specification: text length in NOTES section must not "
231 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
232 "invalid IDFv3 file\n"
233 "* Violation of specification: text length in NOTES section is not "
240 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
241 "invalid IDFv3 file\n"
242 "* Violation of specification: text value in NOTES section is "
264 aBoardFile << setiosflags( ios::fixed ) << setprecision( 1 ) << (
xpos /
IDF_THOU_TO_MM )
270 aBoardFile << setiosflags( ios::fixed ) << setprecision( 5 ) <<
xpos <<
" " <<
ypos <<
" "
274 aBoardFile <<
"\"" <<
text <<
"\"\n";
276 return !aBoardFile.bad();
336 if( aDrillDia < 0.3 )
345 if( !aRefDes.compare(
"BOARD" ) )
349 else if( aRefDes.empty() || !aRefDes.compare(
"NOREFDES" ) )
353 else if( !aRefDes.compare(
"PANEL" ) )
363 if( !aHoleType.compare(
"PIN" ) )
367 else if( !aHoleType.compare(
"VIA" ) )
371 else if( aHoleType.empty() || !aHoleType.compare(
"MTG" ) )
375 else if( !aHoleType.compare(
"TOOL" ) )
391 double ddia = aDrillDia -
dia;
399 if( ddia > -0.00001 && ddia < 0.00001 && p1.
Matches( p2, 0.00001 ) )
417 while( !
FetchIDFLine( aBoardFile, iline, isComment, pos ) && aBoardFile.good() );
419 if( ( !aBoardFile.good() && !aBoardFile.eof() ) || iline.empty() )
421 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
422 "problems reading board drilled holes" ) );
427 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
429 "* Violation of specification: comment within a section (DRILLED "
438 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
440 "* Violation of specification: drill diameter must not be in quotes" ) );
453 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
455 "* Violation of specification: drill diameter is not numeric" ) );
463 ostr <<
"invalid IDF file\n";
464 ostr <<
"* Invalid drill diameter (too small): '" << token <<
"'";
466 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__, ostr.str() ) );
471 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
473 "* Violation of specification: missing X position for drilled hole" ) );
478 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
480 "* Violation of specification: X position in DRILLED HOLES section "
481 "must not be in quotes" ) );
491 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
493 "* Violation of specification: X position in DRILLED HOLES section is "
499 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
501 "* Violation of specification: missing Y position for drilled hole" ) );
506 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
508 "* Violation of specification: Y position in DRILLED HOLES section "
509 "must not be in quotes" ) );
519 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
521 "* Violation of specification: Y position in DRILLED HOLES section is "
529 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
530 "invalid IDFv3 file\n"
531 "* Violation of specification: missing PLATING for drilled hole" ) );
545 ostr <<
"invalid IDFv3 file\n";
546 ostr <<
"* Violation of specification: invalid PLATING type ('" << token <<
"')";
548 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__, ostr.str() ) );
560 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
561 "invalid IDFv3 file\n"
562 "* Violation of specification: missing REFDES for drilled hole" ) );
566 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
567 "invalid IDFv2 file\n"
568 "* Violation of specification: missing HOLE TYPE for drilled "
573 std::string tok1 = token;
579 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
580 "invalid IDFv3 file\n"
581 "* Violation of specification: missing HOLE TYPE for drilled "
586 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
587 "invalid IDFv2 file\n"
588 "* Violation of specification: missing REFDES for drilled hole" ) );
592 std::string tok2 = token;
646 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__,
647 "invalid IDFv3 file\n"
648 "* Violation of specification: missing OWNER for drilled hole" ) );
654 ostr <<
"invalid IDFv3 file\n";
655 ostr <<
"* Violation of specification: invalid OWNER for drilled hole ('" << token
658 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__, ostr.str() ) );
681 ostr <<
"\n* BUG: invalid UNIT type: " <<
static_cast<int>( aBoardUnit );
683 throw(
IDF_ERROR( __FILE__, __FUNCTION__, __LINE__, ostr.str() ) );
703 default: holestr =
"MTG";
break;
711 default: refstr =
"NOREFDES";
break;
723 default: ownstr =
"UNOWNED";
break;
728 aBoardFile << std::setiosflags( std::ios::fixed ) << std::setprecision( 3 ) <<
dia <<
" "
729 << std::setprecision( 5 ) <<
x <<
" " <<
y <<
" " << pltstr.c_str() <<
" "
730 << refstr.c_str() <<
" " << holestr.c_str() <<
" " << ownstr.c_str() <<
"\n";
734 aBoardFile << std::setiosflags( std::ios::fixed ) << std::setprecision( 1 )
737 << pltstr.c_str() <<
" " << refstr.c_str() <<
" " << holestr.c_str() <<
" "
738 << ownstr.c_str() <<
"\n";
774 default:
refdes =
"NOREFDES";
break;
798 double dx =
x - aPoint.
x;
799 double dy =
y - aPoint.
y;
801 double d2 = dx * dx + dy * dy;
803 if( d2 <= aRadius * aRadius )
812 double dx = aPoint.
x -
x;
813 double dy = aPoint.
y -
y;
814 double dist = sqrt( dx * dx + dy * dy );
822 return atan2( aEndPoint.
y - aStartPoint.
y, aEndPoint.
x - aStartPoint.
x );
831 int iang = int (ang /
M_PI * 1800000.0);
833 ang = iang / 10000.0;
850 std::list<IDF_SEGMENT*>::iterator bl = aLines.begin();
851 std::list<IDF_SEGMENT*>::iterator el = aLines.end();
852 std::list<IDF_SEGMENT*>::iterator idx = bl++;
854 double minx = (*idx)->GetMinX();
859 curx = (*bl)->GetMinX();
870 aOutline.
push( *idx );
883 bool complete =
false;
892 while( bl != el && !matched )
896 if( (*bl)->IsCircle() )
909 aOutline.
push( *bl );
910 bl = aLines.erase( bl );
925 while( bl != el && !matched )
929 if( (*bl)->IsCircle() )
943 aOutline.
push( *bl );
944 bl = aLines.erase( bl );
972 aOutline.
push( seg );
1017 double diff =
abs( aAngle ) - 360.0;
1019 if( ( diff < MIN_ANG && diff > -
MIN_ANG ) || ( aAngle < MIN_ANG && aAngle > -
MIN_ANG )
1020 || ( !aFromKicad ) )
1026 if( diff < MIN_ANG && diff > -
MIN_ANG )
1054 ang = (ang / 180.0) *
M_PI;
1063 return startPoint.Matches( aPoint, aRadius );
1069 return endPoint.Matches( aPoint, aRadius );
1095 double h = sqrt( dh2 );
1102 if(
angle < -180.0 )
1104 else if(
angle > 180 )
1107 center.x = h * cos( offAng ) + xm;
1108 center.y = h * sin( offAng ) + ym;
1116 double diff =
abs(
angle ) - 360.0;
1197 if(
outline.front()->IsCircle() )
1209 double a1 =
outline.front()->angle;
1210 double a2 =
outline.back()->angle;
1212 if( ( a1 < -MIN_ANG || a1 >
MIN_ANG ) && ( a2 < -MIN_ANG || a2 >
MIN_ANG ) )
1257 double winding =
dir + (
outline.front()->startPoint.x -
outline.back()->endPoint.x )
1258 * (
outline.front()->startPoint.y +
outline.back()->endPoint.y );
1269 if(
outline.front()->IsCircle() )
1284 cerr <<
"* a circle is being added to a non-empty outline\n";
1289 if(
outline.back()->IsCircle() )
1293 cerr <<
"* a line is being added to a circular outline\n";
1300 cerr <<
"* disjoint segments (current start point != last end point)\n";
1303 cerr <<
"* end point: " <<
outline.back()->endPoint.x <<
", "
1304 <<
outline.back()->endPoint.y <<
"\n";
1312 double ang =
outline.back()->angle;
1313 double oang =
outline.back()->offsetAngle;
1316 if( ang < -MIN_ANG || ang >
MIN_ANG )
1321 oang = ( oang + ang / 2.0 ) *
M_PI / 180.0;
1322 double midx =
outline.back()->center.x +
radius * cos( oang );
1323 double midy =
outline.back()->center.y +
radius * sin( oang );
1325 dir += (
outline.back()->endPoint.x - midx ) * (
outline.back()->endPoint.y + midy );
1327 dir += ( midx -
outline.back()->startPoint.x ) * ( midy +
outline.back()->startPoint.y );
void write(std::ostream &aBoardFile, IDF3::IDF_UNIT aBoardUnit)
Write a single line representing a hole within a .DRILLED_HOLES section.
double GetDrillXPos() const
IDF3::KEY_PLATING GetDrillPlating()
double GetDrillYPos() const
bool Matches(double aDrillDia, double aPosX, double aPosY) const
Return true if the given drill diameter and location matches the diameter and location of this IDF_DR...
double GetDrillDia() const
const std::string & GetDrillRefDes()
const std::string & GetDrillHoleType()
IDF_DRILL_DATA()
Create an empty drill entry which can be populated by the read() function.
bool read(std::istream &aBoardFile, IDF3::IDF_UNIT aBoardUnit, IDF3::FILE_STATE aBoardState, IDF3::IDF_VERSION aIdfVersion)
Read a drill entry from an IDFv3 file.
IDF3::KEY_PLATING plating
const std::string & GetText()
void SetSize(double aHeight, double aLength)
Set the height and length (mm) of the NOTE entry.
bool readNote(std::istream &aBoardFile, IDF3::FILE_STATE &aBoardState, IDF3::IDF_UNIT aBoardUnit)
Read a note entry from an IDFv3 file.
void GetPosition(double &aXpos, double &aYpos)
bool writeNote(std::ostream &aBoardFile, IDF3::IDF_UNIT aBoardUnit)
Write a note entry to an IDFv3 file.
void SetPosition(double aXpos, double aYpos)
Set the position (mm) of the NOTE entry.
void GetSize(double &aHeight, double &aLength)
void SetText(const std::string &aText)
Set the text to be stored as a NOTE entry.
A segment and winding information for an IDF outline.
std::list< IDF_SEGMENT * > outline
void Clear()
Clear the internal list of outline segments.
bool push(IDF_SEGMENT *item)
Add a segment to the internal segment list.
A point as used by the various IDF related classes.
bool Matches(const IDF_POINT &aPoint, double aRadius=1e-5) const
Return true if the given coordinate point is within the given radius of the point.
double CalcDistance(const IDF_POINT &aPoint) const
Return the Euclidean distance between this point and the given point.
A segment as used in IDFv3 outlines.
double radius
radius of the arc or circle; internally calculated
void CalcCenterAndRadius()
IDF_POINT endPoint
end point coordinates in mm
bool MatchesEnd(const IDF_POINT &aPoint, double aRadius=1e-3)
Return true if the given coordinate is within a radius 'rad' of the end point.
IDF_POINT startPoint
starting point coordinates in mm
void SwapEnds()
Swap the start and end points and alters internal variables as necessary for arcs.
double angle
included angle (degrees) according to IDFv3 specification
IDF_SEGMENT()
Initialize the internal variables.
bool MatchesStart(const IDF_POINT &aPoint, double aRadius=1e-3)
Return true if the given coordinate is within a radius 'rad' of the start point.
double offsetAngle
angle between center and start of arc; internally calculated
IDF_POINT center
center of an arc or circle; internally calculated and not to be set by the user.
FILE_STATE
State values for the IDF parser's input.
KEY_REFDES
A component's Reference Designator.
KEY_PLATING
The plating condition of a hole.
bool GetIDFString(const std::string &aLine, std::string &aIDFString, bool &hasQuotes, int &aIndex)
Parse a line retrieved via FetchIDFLine() and returns the first IDF string found from the starting po...
bool FetchIDFLine(std::istream &aModel, std::string &aLine, bool &isComment, std::streampos &aFilePos)
Retrieve a single line from an IDF file and performs minimal processing.
IDF_VERSION
The supported IDF versions (3.0 and 2.0 ONLY).
IDF_UNIT
The native unit of the board and of component outlines.
bool CompareToken(const char *aTokenString, const std::string &aInputString)
Perform a case-insensitive comparison of a token string and an input string.
KEY_OWNER
The type of CAD which has ownership an object.
void GetOutline(std::list< IDF_SEGMENT * > &aLines, IDF_OUTLINE &aOutline)
Take contiguous elements from 'aLines' and stuffs them into 'aOutline'; elements put into the outline...
KEY_HOLETYPE
The purpose of an IDF hole.
double CalcAngleDeg(const IDF_POINT &aStartPoint, const IDF_POINT &aEndPoint)
Calculate the angle (degrees) between the horizon and the segment aStartPoint to aEndPoint.
bool ParseOwner(const std::string &aToken, IDF3::KEY_OWNER &aOwner)
Parse the input string for a valid IDF Owner type.
double CalcAngleRad(const IDF_POINT &aStartPoint, const IDF_POINT &aEndPoint)
Calculate the angle (radians) between the horizon and the segment aStartPoint to aEndPoint.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
virtual const char * what() const noexcept override
IDF_ERROR(const char *aSourceFile, const char *aSourceMethod, int aSourceLine, const std::string &aMessage) noexcept
virtual ~IDF_ERROR() noexcept