summaryrefslogtreecommitdiff
path: root/pcbnew/router/pns_meander.h
diff options
context:
space:
mode:
Diffstat (limited to 'pcbnew/router/pns_meander.h')
-rw-r--r--pcbnew/router/pns_meander.h514
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