diff options
Diffstat (limited to 'pcbnew/router/pns_meander.h')
-rw-r--r-- | pcbnew/router/pns_meander.h | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/pcbnew/router/pns_meander.h b/pcbnew/router/pns_meander.h new file mode 100644 index 0000000..5d1ae51 --- /dev/null +++ b/pcbnew/router/pns_meander.h @@ -0,0 +1,514 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2015 CERN + * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __PNS_MEANDER_H +#define __PNS_MEANDER_H + +#include <math/vector2d.h> + +#include <geometry/shape.h> +#include <geometry/shape_line_chain.h> + +class PNS_MEANDER_PLACER_BASE; + +///< Shapes of available meanders +enum PNS_MEANDER_TYPE { + MT_SINGLE, // _|^|_, single-sided + MT_START, // _|^| + MT_FINISH, // |^|_ + MT_TURN, // |^| or |_| + MT_CHECK_START, // try fitting a start type, but don't produce a line + MT_CHECK_FINISH, // try fitting a finish type, but don't produce a line + MT_CORNER, // line corner + MT_EMPTY // no meander (straight line) +}; + +/** + * Class PNS_MEANDER_SETTINGS + * + * Holds dimensions for the meandering algorithm. + */ +class PNS_MEANDER_SETTINGS +{ +public: + + ///> meander corner shape + enum CornerType { + ROUND = 1, // rounded (90 degree arc) + CHAMFER // chamfered (45 degree segment) + }; + + PNS_MEANDER_SETTINGS() + { + m_minAmplitude = 100000; + m_maxAmplitude = 1000000; + m_step = 50000; + m_spacing = 600000; + m_targetLength = 100000000; + m_targetSkew = 0; + m_cornerType = ROUND; + m_cornerRadiusPercentage = 100; + m_lengthTolerance = 100000; + m_cornerArcSegments = 8; + } + + ///> minimum meandering amplitude + int m_minAmplitude; + ///> maximum meandering amplitude + int m_maxAmplitude; + ///> meandering period/spacing (see dialog picture for explanation) + int m_spacing; + ///> amplitude/spacing adjustment step + int m_step; + ///> desired length of the tuned line/diff pair + int m_targetLength; + ///> type of corners for the meandered line + CornerType m_cornerType; + ///> rounding percentage (0 - 100) + int m_cornerRadiusPercentage; + ///> allowable tuning error + int m_lengthTolerance; + ///> number of line segments for arc approximation + int m_cornerArcSegments; + ///> target skew value for diff pair de-skewing + int m_targetSkew; +}; + +class PNS_MEANDERED_LINE; + +/** + * Class PNS_MEANDER_SETTINGS + * + * Holds the geometry of a single meander. + */ +class PNS_MEANDER_SHAPE +{ +public: + /** + * Constructor + * + * @param aPlacer the meander placer instance + * @param aWidth width of the meandered line + * @param aIsDual when true, the shape contains two meandered + * lines at a given offset (diff pairs) + */ + PNS_MEANDER_SHAPE( PNS_MEANDER_PLACER_BASE *aPlacer, int aWidth, bool aIsDual = false ) : + m_placer( aPlacer ), + m_dual( aIsDual ), + m_width( aWidth ), + m_baselineOffset( 0 ) + { + // Do not leave unitialized members, and keep static analyser quiet: + m_type = MT_SINGLE; + m_amplitude = 0; + m_side = false; + m_baseIndex = 0; + m_currentTarget = NULL; + m_meanCornerRadius = 0; + } + + /** + * Function SetType() + * + * Sets the type of the meander. + */ + void SetType( PNS_MEANDER_TYPE aType ) + { + m_type = aType; + } + + /** + * Function Type() + * + * @return the type of the meander. + */ + PNS_MEANDER_TYPE Type() const + { + return m_type; + } + + /** + * Function SetBaseIndex() + * + * Sets an auxillary index of the segment being meandered in its original PNS_LINE. + */ + void SetBaseIndex( int aIndex ) + { + m_baseIndex = aIndex; + } + + /** + * Function BaseIndex() + * + * @return auxillary index of the segment being meandered in its original PNS_LINE. + */ + int BaseIndex() const + { + return m_baseIndex; + } + + /** + * Function Amplitude() + * + * @return the amplitude of the meander shape. + */ + int Amplitude() const + { + return m_amplitude; + } + + /** + * Function MakeCorner() + * + * Creates a dummy meander shape representing a line corner. Used to define + * the starts/ends of meandered segments. + * @param aP1 corner point of the 1st line + * @param aP2 corner point of the 2nd line (if m_dual == true) + */ + void MakeCorner( VECTOR2I aP1, VECTOR2I aP2 = VECTOR2I( 0, 0 ) ); + + /** + * Function Resize() + * + * Changes the amplitude of the meander shape to aAmpl and recalculates + * the resulting line chain. + * @param aAmpl new amplitude. + */ + void Resize( int aAmpl ); + + /** + * Function Recalculate() + * + * Recalculates the line chain representing the meanders's shape. + */ + void Recalculate(); + + /** + * Function IsDual() + * + * @return true if the shape represents 2 parallel lines (diff pair). + */ + bool IsDual() const + { + return m_dual; + } + + /** + * Function Side() + * + * @return true if the meander is to the right of its base segment. + */ + bool Side() const + { + return m_side; + } + + /** + * Function End() + * + * @return end vertex of the base segment of the meander shape. + */ + VECTOR2I End() const + { + return m_clippedBaseSeg.B; + } + + /** + * Function CLine() + * + * @return the line chain representing the shape of the meander. + */ + const SHAPE_LINE_CHAIN& CLine( int aShape ) const + { + return m_shapes[aShape]; + } + + /** + * Function MakeEmpty() + * + * Replaces the meander with straight bypass line(s), effectively + * clearing it. + */ + void MakeEmpty(); + + /** + * Function Fit() + * + * Attempts to fit a meander of a given type onto a segment, avoiding + * collisions with other board features. + * @param aType type of meander shape + * @param aSeg base segment for meandering + * @param aP start point of the meander + * @param aSide side of aSeg to put the meander on (true = right) + * @return true on success. + */ + bool Fit( PNS_MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP, bool aSide ); + + /** + * Function BaseSegment() + * + * Returns the base segment the meadner was fitted to. + * @return the base segment. + */ + const SEG& BaseSegment() const + { + return m_clippedBaseSeg; + } + + /** + * Function BaselineLength() + * + * @return length of the base segment for the meander (i.e. + * the minimum tuned length. + */ + int BaselineLength() const; + + /** + * Function MaxTunableLength() + * + * @return the length of the fitted line chain. + */ + int MaxTunableLength() const; + + /** + * Function Settings() + * + * @return the current meandering settings. + */ + const PNS_MEANDER_SETTINGS& Settings() const; + + /** + * Function Width() + * + * @return width of the meandered line. + */ + int Width() const + { + return m_width; + } + + /** + * Function SetBaselineOffset() + * + * Sets the parallel offset between the base segment and the meandered + * line. Used for dual menaders (diff pair) only. + * @param aOffset the offset + */ + void SetBaselineOffset( int aOffset ) + { + m_baselineOffset = aOffset; + } + +private: + friend class PNS_MEANDERED_LINE; + + ///> starts turtle drawing + void start( SHAPE_LINE_CHAIN* aTarget, const VECTOR2D& aWhere, const VECTOR2D& aDir ); + ///> moves turtle forward by aLength + void forward( int aLength ); + ///> turns the turtle by aAngle + void turn( int aAngle ); + ///> tells the turtle to draw an arc of given radius and turn direction + void arc( int aRadius, bool aSide ); + ///> tells the turtle to draw an U-like shape + void uShape( int aSides, int aCorner, int aTop ); + + ///> generates a 90-degree circular arc + SHAPE_LINE_CHAIN circleQuad( VECTOR2D aP, VECTOR2D aDir, bool aSide ); + + ///> reflects a point onto other side of a given segment + VECTOR2I reflect( VECTOR2I aP, const SEG& aLine ); + + ///> produces a meander shape of given type + SHAPE_LINE_CHAIN genMeanderShape( VECTOR2D aP, VECTOR2D aDir, bool aSide, PNS_MEANDER_TYPE aType, int aAmpl, int aBaselineOffset = 0 ); + + ///> recalculates the clipped baseline after the parameters of + ///> the meander have been changed. + void updateBaseSegment(); + + ///> returns sanitized corner radius value + int cornerRadius() const; + + ///> returns sanitized spacing value + int spacing() const; + + ///> the type + PNS_MEANDER_TYPE m_type; + ///> the placer that placed this meander + PNS_MEANDER_PLACER_BASE* m_placer; + ///> dual or single line + bool m_dual; + ///> width of the line + int m_width; + ///> amplitude of the meander + int m_amplitude; + ///> offset wrs the base segment (dual only) + int m_baselineOffset; + ///> average radius of meander corners (for correction of DP meanders) + int m_meanCornerRadius; + ///> first point of the meandered line + VECTOR2I m_p0; + ///> base segment (unclipped) + SEG m_baseSeg; + ///> base segment (clipped) + SEG m_clippedBaseSeg; + ///> side (true = right) + bool m_side; + ///> the actual shapes (0 used for single, both for dual) + SHAPE_LINE_CHAIN m_shapes[2]; + ///> index of the meandered segment in the base line + int m_baseIndex; + ///> current turtle direction + VECTOR2D m_currentDir; + ///> current turtle position + VECTOR2D m_currentPos; + ///> the line the turtle is drawing on + SHAPE_LINE_CHAIN* m_currentTarget; +}; + + +/** + * Class PNS_MEANDERED_LINE + * + * Represents a set of meanders fitted over a single or two lines. + */ +class PNS_MEANDERED_LINE +{ +public: + PNS_MEANDERED_LINE() + { + // Do not leave unitialized members, and keep static analyser quiet: + m_placer = NULL; + m_dual = false; + m_width = 0; + m_baselineOffset = 0; + } + + /** + * Constructor + * + * @param aPlacer the meander placer instance + * @param aIsDual when true, the meanders are generated for two coupled lines + */ + PNS_MEANDERED_LINE( PNS_MEANDER_PLACER_BASE* aPlacer, bool aIsDual = false ) : + m_placer( aPlacer ), + m_dual( aIsDual ) + { + // Do not leave unitialized members, and keep static analyser quiet: + m_width = 0; + m_baselineOffset = 0; + } + + ~PNS_MEANDERED_LINE() + { + Clear(); + } + + /** + * Function AddCorner() + * + * Creates a dummy meander shape representing a line corner. Used to define + * the starts/ends of meandered segments. + * @param aA corner point of the 1st line + * @param aB corner point of the 2nd line (if m_dual == true) + */ + void AddCorner( const VECTOR2I& aA, const VECTOR2I& aB = VECTOR2I( 0, 0 ) ); + + /** + * Function AddMeander() + * + * Adds a new meander shape the the meandered line. + * @param aShape the meander shape to add + */ + void AddMeander( PNS_MEANDER_SHAPE* aShape ); + + /** + * Function Clear() + * + * Clears the line geometry, removing all corners and meanders. + */ + void Clear(); + + /** + * Function SetWidth() + * + * Sets the line width. + */ + void SetWidth( int aWidth ) + { + m_width = aWidth; + } + + /** + * Function MeanderSegment() + * + * Fits maximum amplitude meanders on a given segment and adds to the + * current line. + * @param aSeg the base segment to meander + * @param aBaseIndex index of the base segment in the original line + */ + void MeanderSegment( const SEG& aSeg, int aBaseIndex = 0 ); + + /// @copydoc PNS_MEANDER_SHAPE::SetBaselineOffset() + void SetBaselineOffset( int aOffset ) + { + m_baselineOffset = aOffset; + } + + /** + * Function Meanders() + * + * @return set of meander shapes for this line + */ + std::vector<PNS_MEANDER_SHAPE*>& Meanders() + { + return m_meanders; + } + + /** + * Function CheckSelfIntersections() + * + * Checks if the given shape is intersecting with any other meander in + * the current line. + * @param aShape the shape to check + * @param aClearance clearance value + * @return true, if the meander shape is not colliding + */ + bool CheckSelfIntersections ( PNS_MEANDER_SHAPE* aShape, int aClearance ); + + /** + * Function Settings() + * + * @return the current meandering settings. + */ + const PNS_MEANDER_SETTINGS& Settings() const; + +private: + VECTOR2I m_last; + + PNS_MEANDER_PLACER_BASE* m_placer; + std::vector<PNS_MEANDER_SHAPE*> m_meanders; + + bool m_dual; + int m_width; + int m_baselineOffset; +}; + +#endif // __PNS_MEANDER_H |