summaryrefslogtreecommitdiff
path: root/utils/idftools/idf_common.h
diff options
context:
space:
mode:
Diffstat (limited to 'utils/idftools/idf_common.h')
-rw-r--r--utils/idftools/idf_common.h711
1 files changed, 711 insertions, 0 deletions
diff --git a/utils/idftools/idf_common.h b/utils/idftools/idf_common.h
new file mode 100644
index 0000000..398f8f8
--- /dev/null
+++ b/utils/idftools/idf_common.h
@@ -0,0 +1,711 @@
+/**
+ * @file idf_common.h
+ */
+
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2013-2014 Cirilo Bernardo
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef IDF_COMMON_H
+#define IDF_COMMON_H
+
+#include <list>
+#include <fstream>
+#include <exception>
+#include <string>
+#include <cmath>
+
+// differences in angle smaller than MIN_ANG are considered equal
+#define MIN_ANG (0.01)
+
+class IDF_POINT;
+class IDF_SEGMENT;
+class IDF_DRILL_DATA;
+class IDF_OUTLINE;
+class IDF_LIB;
+
+
+struct IDF_ERROR : std::exception
+{
+ std::string message;
+
+ IDF_ERROR( const char* aSourceFile,
+ const char* aSourceMethod,
+ int aSourceLine,
+ const std::string& aMessage ) throw();
+
+ virtual ~IDF_ERROR() throw();
+
+ virtual const char* what() const throw();
+};
+
+
+namespace IDF3 {
+
+ /**
+ * ENUM FILE_STATE
+ * represents state values for the IDF parser's input
+ */
+ enum FILE_STATE
+ {
+ FILE_START = 0, // no data has been read; expecting .HEADER
+ FILE_HEADER, // header has been read; expecting .BOARD_OUTLINE
+ FILE_OUTLINE, // board outline has been read; most sections can be accepted
+ FILE_PLACEMENT, // placement has been read; no further sections can be accepted
+ FILE_INVALID, // file is invalid
+ FILE_ERROR // other errors while processing the file
+ };
+
+ /**
+ * ENUM IDF_VERSION
+ * represents the supported IDF versions (3.0 and 2.0 ONLY)
+ */
+ enum IDF_VERSION
+ {
+ IDF_V2 = 0, // version 2 has read support only; files written as IDFv3
+ IDF_V3 // version 3 has full read/write support
+ };
+
+ /**
+ * ENUM KEY_OWNER
+ * represents the type of CAD which has ownership an object
+ */
+ enum KEY_OWNER
+ {
+ UNOWNED = 0, //< either MCAD or ECAD may modify a feature
+ MCAD, //< only MCAD may modify a feature
+ ECAD //< only ECAD may modify a feature
+ };
+
+ /**
+ * ENUM KEY_HOLETYPE
+ * represents the purpose of an IDF hole
+ */
+ enum KEY_HOLETYPE
+ {
+ PIN = 0, //< drill hole is for a pin
+ VIA, //< drill hole is for a via
+ MTG, //< drill hole is for mounting
+ TOOL, //< drill hole is for tooling
+ OTHER //< user has specified a custom type
+ };
+
+ /**
+ * ENUM KEY_PLATING
+ * represents the plating condition of a hole
+ */
+ enum KEY_PLATING
+ {
+ PTH = 0, //< Plate-Through Hole
+ NPTH //< Non-Plate-Through Hole
+ };
+
+ /**
+ * ENUM KEY_REFDES
+ * represents a component's Reference Designator
+ */
+ enum KEY_REFDES
+ {
+ BOARD = 0, //< feature is associated with the board
+ NOREFDES, //< feature is associated with a component with no RefDes
+ PANEL, //< feature is associated with an IDF panel
+ REFDES //< reference designator as assigned by the CAD software
+ };
+
+ /**
+ * ENUM CAD_TYPE
+ * represents the class of CAD program which is opening or modifying a file
+ */
+ enum CAD_TYPE
+ {
+ CAD_ELEC = 0, //< An Electrical CAD is opening/modifying the file
+ CAD_MECH, //< A Mechanical CAD is opening/modifying the file
+ CAD_INVALID
+ };
+
+ /**
+ * ENUM IDF_LAYER
+ * represents the various IDF layer classes and groupings
+ */
+ enum IDF_LAYER
+ {
+ LYR_TOP = 0,
+ LYR_BOTTOM,
+ LYR_BOTH,
+ LYR_INNER,
+ LYR_ALL,
+ LYR_INVALID
+ };
+
+ /**
+ * ENUM OUTLINE_TYPE
+ * identifies the class of outline
+ */
+ enum OUTLINE_TYPE
+ {
+ OTLN_BOARD = 0,
+ OTLN_OTHER,
+ OTLN_PLACE,
+ OTLN_ROUTE,
+ OTLN_PLACE_KEEPOUT,
+ OTLN_ROUTE_KEEPOUT,
+ OTLN_VIA_KEEPOUT,
+ OTLN_GROUP_PLACE,
+ OTLN_COMPONENT,
+ OTLN_INVALID
+ };
+
+ /**
+ * ENUM COMP_TYPE
+ * identifies whether a component is a mechanical or electrical part
+ */
+ enum COMP_TYPE
+ {
+ COMP_ELEC = 0, //< Component library object is an electrical part
+ COMP_MECH, //< Component library object is a mechanical part
+ COMP_INVALID
+ };
+
+ /**
+ * ENUM IDF_UNIT
+ * represents the native unit of the board and of component outlines
+ */
+ enum IDF_UNIT
+ {
+ UNIT_MM = 0, //< Units in the file are in millimeters
+ UNIT_THOU, //< Units in the file are in mils (aka thou)
+ UNIT_TNM, //< Deprecated Ten Nanometer Units from IDFv2
+ UNIT_INVALID
+ };
+
+ /**
+ * ENUM IDF_PLACEMENT
+ * represents the placement status of a component
+ */
+ enum IDF_PLACEMENT
+ {
+ PS_UNPLACED = 0, //< component location on the board has not been specified
+ PS_PLACED, //< component location has been specified and may be modified by ECAD or MCAD
+ PS_MCAD, //< component location has been specified and may only be modified by MCAD
+ PS_ECAD, //< component location has been specified and may only be modified by ECAD
+ PS_INVALID
+ };
+
+ /**
+ * Function CalcAngleRad
+ * calculates the angle (radians) between the horizon and the segment aStartPoint to aEndPoint
+ *
+ * @param aStartPoint is the start point of a line segment
+ * @param aEndPoint is the end point of a line segment
+ *
+ * @return double: the angle in radians
+ */
+ double CalcAngleRad( const IDF_POINT& aStartPoint, const IDF_POINT& aEndPoint );
+
+
+ /**
+ * Function CalcAngleDeg
+ * calculates the angle (degrees) between the horizon and the segment aStartPoint to aEndPoint
+ *
+ * @param aStartPoint is the start point of a line segment
+ * @param aEndPoint is the end point of a line segment
+ *
+ * @return double: the angle in degrees
+ */
+ double CalcAngleDeg( const IDF_POINT& aStartPoint, const IDF_POINT& aEndPoint );
+
+ /**
+ * Function GetOutline
+ * takes contiguous elements from 'aLines' and stuffs them into 'aOutline'; elements put
+ * into the outline are deleted from aLines. This function is useful for sorting the jumbled
+ * mess of line segments and arcs which represent a board outline and cutouts in KiCad.
+ * The function will determine which segment element within aLines contains the leftmost
+ * point and retrieve the outline of which that segment is part.
+ *
+ * @param aLines (input/output) is a list of IDF segments which comprise an outline and
+ * cutouts.
+ * @param aOutline (output) is the ordered set of segments
+ */
+ void GetOutline( std::list<IDF_SEGMENT*>& aLines,
+ IDF_OUTLINE& aOutline );
+
+#ifdef DEBUG_IDF
+ // prints out segment information for debug purposes
+ void PrintSeg( IDF_SEGMENT* aSegment );
+#endif
+}
+
+
+/**
+ * Class IDF_NOTE
+ * represents an entry in the NOTE section of an IDF file
+ */
+class IDF_NOTE
+{
+friend class IDF3_BOARD;
+private:
+ std::string text; // note text as per IDFv3
+ double xpos; // text X position as per IDFv3
+ double ypos; // text Y position as per IDFv3
+ double height; // text height as per IDFv3
+ double length; // text length as per IDFv3
+
+ /**
+ * Function readNote
+ * reads a note entry from an IDFv3 file
+ *
+ * @param aBoardFile is an open BOARD file; the file position must be set to the start of a NOTE entry
+ * @param aBoardState is the parser's current state value
+ * @param aBoardUnit is the BOARD file's native units (MM or THOU)
+ *
+ * @return bool: true if a note item was read, false otherwise. In case of unrecoverable errors
+ * an exception is thrown
+ */
+ bool readNote( std::ifstream& aBoardFile, IDF3::FILE_STATE& aBoardState, IDF3::IDF_UNIT aBoardUnit );
+
+ /**
+ * Function writeNote
+ * writes a note entry to an IDFv3 file
+ *
+ * @param aBoardFile is an open BOARD file; the file position must be within a NOTE section
+ * @param aBoardUnit is the BOARD file's native units (MM or THOU)
+ *
+ * @return bool: true if the item was successfully written, false otherwise. In case of
+ * unrecoverable errors an exception is thrown
+ */
+ bool writeNote( std::ofstream& aBoardFile, IDF3::IDF_UNIT aBoardUnit );
+
+public:
+ IDF_NOTE();
+
+ /**
+ * Function SetText
+ * sets the text to be stored as a NOTE entry
+ */
+ void SetText( const std::string& aText );
+
+ /**
+ * Function SetPosition
+ * sets the position (mm) of the NOTE entry
+ */
+ void SetPosition( double aXpos, double aYpos );
+
+ /**
+ * Function SetSize
+ * sets the height and length (mm) of the NOTE entry
+ */
+ void SetSize( double aHeight, double aLength );
+
+ /**
+ * Function GetText
+ * returns the string stored in the note entry
+ */
+ const std::string& GetText( void );
+
+ /**
+ * Function GetText
+ * returns the position (mm) of the note entry
+ */
+ void GetPosition( double& aXpos, double& aYpos );
+
+ /**
+ * Function GetText
+ * returns the height and length (mm) of the note entry
+ */
+ void GetSize( double& aHeight, double& aLength );
+};
+
+
+/**
+ * @Class IDF_DRILL_DATA
+ * contains information describing a drilled hole and is responsible for
+ * writing this information to a file in compliance with the IDFv3 specification.
+ */
+class IDF_DRILL_DATA
+{
+friend class IDF3_BOARD;
+friend class IDF3_COMPONENT;
+private:
+ double dia;
+ double x;
+ double y;
+ IDF3::KEY_PLATING plating;
+ IDF3::KEY_REFDES kref;
+ IDF3::KEY_HOLETYPE khole;
+ std::string refdes;
+ std::string holetype;
+ IDF3::KEY_OWNER owner;
+
+ /**
+ * Function read
+ * read a drill entry from an IDFv3 file
+ *
+ * @param aBoardFile is an open IDFv3 file; the file position must be within the DRILLED_HOLES section
+ * @param aBoardUnit is the board file's native unit (MM or THOU)
+ * @param aBoardState is the state value of the parser
+ *
+ * @return bool: true if data was successfully read, otherwise false. In case of an
+ * unrecoverable error an exception is thrown
+ */
+ bool read( std::ifstream& aBoardFile, IDF3::IDF_UNIT aBoardUnit, IDF3::FILE_STATE aBoardState,
+ IDF3::IDF_VERSION aIdfVersion );
+
+ /**
+ * Function write
+ * writes a single line representing a hole within a .DRILLED_HOLES section
+ * In case of an unrecoverable error an exception is thrown.
+ *
+ * @param aBoardFile is an open BOARD file
+ * @param aBoardUnit is the native unit of the output file
+ */
+ void write( std::ofstream& aBoardFile, IDF3::IDF_UNIT aBoardUnit );
+
+public:
+ /**
+ * Constructor IDF_DRILL_DATA
+ * creates an empty drill entry which can be populated by the
+ * read() function
+ */
+ IDF_DRILL_DATA();
+
+ /**
+ * Constructor IDF_DRILL_DATA
+ * creates a drill entry with information compliant with the
+ * IDFv3 specifications.
+ * @param aDrillDia : drill diameter
+ * @param aPosX : X coordinate of the drill center
+ * @param aPosY : Y coordinate of the drill center
+ * @param aPlating : flag, PTH or NPTH
+ * @param aRefDes : component Reference Designator
+ * @param aHoleType : purpose of hole
+ * @param aOwner : one of MCAD, ECAD, UNOWNED
+ */
+ IDF_DRILL_DATA( double aDrillDia, double aPosX, double aPosY,
+ IDF3::KEY_PLATING aPlating,
+ const std::string aRefDes,
+ const std::string aHoleType,
+ IDF3::KEY_OWNER aOwner );
+
+ /**
+ * Function Matches
+ * returns true if the given drill diameter and location
+ * matches the diameter and location of this IDF_DRILL_DATA object
+ *
+ * @param aDrillDia is the drill diameter (mm)
+ * @param aPosX is the X position (mm) of the drilled hole
+ * @param aPosY is the Y position (mm) of the drilled hole
+ *
+ * @return bool: true if the diameter and position match this object
+ */
+ bool Matches( double aDrillDia, double aPosX, double aPosY );
+
+ /**
+ * Function GettDrillDia
+ * returns the drill diameter in mm
+ */
+ double GetDrillDia();
+
+ /**
+ * Function GettDrillXPos
+ * returns the drill's X position in mm
+ */
+ double GetDrillXPos();
+
+ /**
+ * Function GettDrillYPos
+ * returns the drill's Y position in mm
+ */
+ double GetDrillYPos();
+
+ /**
+ * Function GetDrillPlating
+ * returns the plating value (PTH, NPTH)
+ */
+ IDF3::KEY_PLATING GetDrillPlating();
+
+ /**
+ * Function GetDrillRefDes
+ * returns the reference designator of the hole; this
+ * may be a component reference designator, BOARD, or
+ * NOREFDES as per IDFv3.
+ */
+ const std::string& GetDrillRefDes();
+
+ /**
+ * Function GetDrillHoleType
+ * returns the classification of the hole; this may be one of
+ * PIN, VIA, MTG, TOOL, or a user-specified string
+ */
+ const std::string& GetDrillHoleType();
+
+ IDF3::KEY_OWNER GetDrillOwner( void )
+ {
+ return owner;
+ }
+};
+
+
+/**
+ * @Class IDF_POINT
+ * represents a point as used by the various IDF related classes
+ */
+class IDF_POINT
+{
+public:
+ double x; // < X coordinate
+ double y; // < Y coordinate
+
+ IDF_POINT()
+ {
+ x = 0.0;
+ y = 0.0;
+ }
+
+ /**
+ * Function Matches()
+ * returns true if the given coordinate point is within the given radius
+ * of the point.
+ *
+ * @param aPoint : coordinates of the point being compared
+ * @param aRadius : radius (mm) within which the points are considered the same
+ *
+ * @return bool: true if this point matches the given point
+ */
+ bool Matches( const IDF_POINT& aPoint, double aRadius = 1e-5 );
+
+ /**
+ * Function CalcDistance()
+ * returns the Euclidean distance between this point and the given point
+ *
+ * @param aPoint : coordinates of the point whose distance is to be determined
+ *
+ * @return double: distance between this point and aPoint
+ */
+ double CalcDistance( const IDF_POINT& aPoint ) const;
+};
+
+
+/**
+ * @Class IDF_SEGMENT
+ * represents a geometry segment as used in IDFv3 outlines; it may be any of
+ * an arc, line segment, or circle
+ */
+class IDF_SEGMENT
+{
+private:
+ /**
+ * Function CalcCenterAndRadius()
+ * Calculates the center, radius, and angle between center and start point given the
+ * IDF compliant points and included angle.
+ *
+ * @var startPoint, @var endPoint, and @var angle must be set prior as per IDFv3
+ */
+ void CalcCenterAndRadius( void );
+
+public:
+ IDF_POINT startPoint; ///< starting point coordinates in mm
+ IDF_POINT endPoint; ///< end point coordinates in mm
+ IDF_POINT center; ///< center of an arc or circle; internally calculated and not to be set by the user
+ double angle; ///< included angle (degrees) according to IDFv3 specification
+ double offsetAngle; ///< angle between center and start of arc; internally calculated
+ double radius; ///< radius of the arc or circle; internally calculated
+
+ /**
+ * Constructor IDF_SEGMENT
+ * initializes the internal variables
+ */
+ IDF_SEGMENT();
+
+ /**
+ * Function IDF_SEGMENT
+ * creates a straight segment
+ */
+ IDF_SEGMENT( const IDF_POINT& aStartPoint, const IDF_POINT& aEndPoint );
+
+ /**
+ * Constructor IDF_SEGMENT
+ * creates a straight segment, arc, or circle depending on the angle
+ *
+ * @param aStartPoint : start point (center if using KiCad convention, otherwise IDF convention)
+ * @param aEndPoint : end point (start of arc if using KiCad convention, otherwise IDF convention)
+ * @param aAngle : included angle; the KiCad convention is equivalent to the IDF convention
+ * @param fromKicad : set true if we need to convert from KiCad to IDF convention
+ */
+ IDF_SEGMENT( const IDF_POINT& aStartPoint,
+ const IDF_POINT& aEndPoint,
+ double aAngle,
+ bool aFromKicad );
+
+ /**
+ * Function MatchesStart
+ * returns true if the given coordinate is within a radius 'rad'
+ * of the start point.
+ *
+ * @param aPoint : coordinates of the point (mm) being compared
+ * @param aRadius : radius (mm) within which the points are considered the same
+ *
+ * @return bool: true if the given point matches the start point of this segment
+ */
+ bool MatchesStart( const IDF_POINT& aPoint, double aRadius = 1e-3 );
+
+ /**
+ * Function MatchesEnd
+ * returns true if the given coordinate is within a radius 'rad'
+ * of the end point.
+ *
+ * @param aPoint : coordinates (mm) of the point being compared
+ * @param aRadius : radius (mm) within which the points are considered the same
+ *
+ * @return bool: true if the given point matches the end point of this segment
+ */
+ bool MatchesEnd( const IDF_POINT& aPoint, double aRadius = 1e-3 );
+
+ /**
+ * Function IsCircle
+ * returns true if this segment is a circle
+ */
+ bool IsCircle( void );
+
+ /**
+ * Function GetMinX()
+ * returns the minimum X coordinate of this segment
+ */
+ double GetMinX( void );
+
+ /**
+ * Function SwapEnds()
+ * Swaps the start and end points and alters internal
+ * variables as necessary for arcs
+ */
+ void SwapEnds( void );
+};
+
+
+/**
+ * @Class IDF_OUTLINE
+ * contains segment and winding information for an IDF outline
+ */
+class IDF_OUTLINE
+{
+private:
+ double dir; // accumulator to help determine winding direction
+ std::list<IDF_SEGMENT*> outline; // sequential segments comprising an outline
+
+public:
+ IDF_OUTLINE() { dir = 0.0; }
+ ~IDF_OUTLINE() { Clear(); }
+
+ /**
+ * Function IsCCW
+ * returns true if the current list of points represents a counterclockwise winding
+ */
+ bool IsCCW( void );
+
+ /**
+ * Function IsCircle
+ * returns true if this outline is a circle
+ */
+ bool IsCircle( void );
+
+ /**
+ * Function Clear
+ * clears the internal list of outline segments
+ */
+ void Clear( void )
+ {
+ dir = 0.0;
+
+ while( !outline.empty() )
+ {
+ delete outline.front();
+ outline.pop_front();
+ }
+ }
+
+ /**
+ * Function size
+ * returns the size of the internal segment list
+ */
+ size_t size( void )
+ {
+ return outline.size();
+ }
+
+ /**
+ * Function empty
+ * returns true if the internal segment list is empty
+ */
+ bool empty( void )
+ {
+ return outline.empty();
+ }
+
+ /**
+ * Function front
+ * returns the front() iterator of the internal segment list
+ */
+ IDF_SEGMENT*& front( void )
+ {
+ return outline.front();
+ }
+
+ /**
+ * Function back
+ * returns the back() iterator of the internal segment list
+ */
+ IDF_SEGMENT*& back( void )
+ {
+ return outline.back();
+ }
+
+ /**
+ * Function begin
+ * returns the begin() iterator of the internal segment list
+ */
+ std::list<IDF_SEGMENT*>::iterator begin( void )
+ {
+ return outline.begin();
+ }
+
+ /**
+ * Function end
+ * returns the end() iterator of the internal segment list
+ */
+ std::list<IDF_SEGMENT*>::iterator end( void )
+ {
+ return outline.end();
+ }
+
+ /**
+ * Function push
+ * adds a segment to the internal segment list; segments must be added
+ * in order so that startPoint[N] == endPoint[N - 1]
+ *
+ * @param item is a pointer to the segment to add to the outline
+ *
+ * @return bool: true if the segment was added, otherwise false
+ * (outline restrictions have been violated)
+ */
+ bool push( IDF_SEGMENT* item );
+};
+
+#endif // IDF_COMMON_H