From a30894e5a1886d982b5d7894c010e8c326d2fe29 Mon Sep 17 00:00:00 2001 From: Thomas Pointhuber Date: Sun, 11 Apr 2021 14:28:32 +0200 Subject: [PATCH] Allow SHAPE_LINE_CHAIN and SHAPE_ARC to be mirrored using a SEG --- libs/kimath/include/geometry/seg.h | 25 +++++++++++++++++++ libs/kimath/include/geometry/shape_arc.h | 2 ++ .../include/geometry/shape_line_chain.h | 6 +++++ libs/kimath/src/geometry/shape_arc.cpp | 10 ++++++++ libs/kimath/src/geometry/shape_line_chain.cpp | 10 ++++++++ pcbnew/router/pns_meander.cpp | 22 +--------------- pcbnew/router/pns_meander.h | 3 --- 7 files changed, 54 insertions(+), 24 deletions(-) diff --git a/libs/kimath/include/geometry/seg.h b/libs/kimath/include/geometry/seg.h index a8f10288c9..ef74bfeed3 100644 --- a/libs/kimath/include/geometry/seg.h +++ b/libs/kimath/include/geometry/seg.h @@ -180,6 +180,13 @@ public: */ const VECTOR2I NearestPoint( const SEG &aSeg ) const; + /** + * Reflect a point using this segment as axis. + * + * @return the reflected point + */ + const VECTOR2I ReflectPoint( const VECTOR2I& aP ) const; + /** * Compute intersection point of segment (this) with segment \a aSeg. * @@ -448,6 +455,24 @@ inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const return A + VECTOR2I( xp, yp ); } +inline const VECTOR2I SEG::ReflectPoint( const VECTOR2I& aP ) const +{ + VECTOR2I d = B - A; + VECTOR2I::extended_type l_squared = d.Dot( d ); + VECTOR2I::extended_type t = d.Dot( aP - A ); + VECTOR2I c; + + if( !l_squared ) + c = aP; + else + { + c.x = A.x + rescale( t, static_cast( d.x ), l_squared ); + c.y = A.y + rescale( t, static_cast( d.y ), l_squared ); + } + + return 2 * c - aP; +} + inline std::ostream& operator<<( std::ostream& aStream, const SEG& aSeg ) { aStream << "[ " << aSeg.A << " - " << aSeg.B << " ]"; diff --git a/libs/kimath/include/geometry/shape_arc.h b/libs/kimath/include/geometry/shape_arc.h index e26b90c0e9..70caf30873 100644 --- a/libs/kimath/include/geometry/shape_arc.h +++ b/libs/kimath/include/geometry/shape_arc.h @@ -131,6 +131,8 @@ public: void Mirror( bool aX = true, bool aY = false, const VECTOR2I& aVector = { 0, 0 } ); + void Mirror( const SEG& axis ); + void Reverse(); SHAPE_ARC Reversed() const; diff --git a/libs/kimath/include/geometry/shape_line_chain.h b/libs/kimath/include/geometry/shape_line_chain.h index 5f884f11d0..4039fa46f5 100644 --- a/libs/kimath/include/geometry/shape_line_chain.h +++ b/libs/kimath/include/geometry/shape_line_chain.h @@ -708,6 +708,12 @@ public: */ void Mirror( bool aX = true, bool aY = false, const VECTOR2I& aRef = { 0, 0 } ); + /** + * Mirrors the line points using an given axis + * @param axis Axis on which to mirror + */ + void Mirror( const SEG& axis ); + /** * Function Rotate * rotates all vertices by a given angle diff --git a/libs/kimath/src/geometry/shape_arc.cpp b/libs/kimath/src/geometry/shape_arc.cpp index 36252e0121..309475ee7d 100644 --- a/libs/kimath/src/geometry/shape_arc.cpp +++ b/libs/kimath/src/geometry/shape_arc.cpp @@ -494,6 +494,16 @@ void SHAPE_ARC::Mirror( bool aX, bool aY, const VECTOR2I& aVector ) } +void SHAPE_ARC::Mirror( const SEG& axis ) +{ + m_start = axis.ReflectPoint( m_start ); + m_end = axis.ReflectPoint( m_end ); + m_mid = axis.ReflectPoint( m_mid ); + + update_bbox(); +} + + void SHAPE_ARC::Reverse() { std::swap( m_start, m_end ); diff --git a/libs/kimath/src/geometry/shape_line_chain.cpp b/libs/kimath/src/geometry/shape_line_chain.cpp index bf8e20cae4..bbec0b869c 100644 --- a/libs/kimath/src/geometry/shape_line_chain.cpp +++ b/libs/kimath/src/geometry/shape_line_chain.cpp @@ -256,6 +256,16 @@ void SHAPE_LINE_CHAIN::Mirror( bool aX, bool aY, const VECTOR2I& aRef ) } +void SHAPE_LINE_CHAIN::Mirror( const SEG& axis ) +{ + for( auto& pt : m_points ) + pt = axis.ReflectPoint( pt ); + + for( auto& arc : m_arcs ) + arc.Mirror( axis ); +} + + void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const VECTOR2I& aP ) { if( aEndIndex < 0 ) diff --git a/pcbnew/router/pns_meander.cpp b/pcbnew/router/pns_meander.cpp index 284aea45fb..b95f5b489e 100644 --- a/pcbnew/router/pns_meander.cpp +++ b/pcbnew/router/pns_meander.cpp @@ -237,25 +237,6 @@ SHAPE_LINE_CHAIN MEANDER_SHAPE::makeMiterShape( VECTOR2D aP, VECTOR2D aDir, bool } -VECTOR2I MEANDER_SHAPE::reflect( VECTOR2I p, const SEG& line ) -{ - typedef int64_t ecoord; - VECTOR2I d = line.B - line.A; - ecoord l_squared = d.Dot( d ); - ecoord t = d.Dot( p - line.A ); - VECTOR2I c, rv; - - if( !l_squared ) - c = p; - else { - c.x = line.A.x + rescale( t, (ecoord) d.x, l_squared ); - c.y = line.A.y + rescale( t, (ecoord) d.y, l_squared ); - } - - return 2 * c - p; -} - - void MEANDER_SHAPE::start( SHAPE_LINE_CHAIN* aTarget, const VECTOR2D& aWhere, const VECTOR2D& aDir ) { m_currentTarget = aTarget; @@ -392,8 +373,7 @@ SHAPE_LINE_CHAIN MEANDER_SHAPE::genMeanderShape( VECTOR2D aP, VECTOR2D aDir, { SEG axis( aP, aP + aDir ); - for( int i = 0; i < lc.PointCount(); i++ ) - lc.SetPoint( i, reflect( lc.CPoint( i ), axis ) ); + lc.Mirror( axis ); } return lc; diff --git a/pcbnew/router/pns_meander.h b/pcbnew/router/pns_meander.h index 1969a2e68a..2de3617801 100644 --- a/pcbnew/router/pns_meander.h +++ b/pcbnew/router/pns_meander.h @@ -297,9 +297,6 @@ private: ///< Generate a 90-degree circular arc. SHAPE_LINE_CHAIN makeMiterShape( VECTOR2D aP, VECTOR2D aDir, bool aSide ); - ///< Reflect a point onto other side of a given segment. - VECTOR2I reflect( VECTOR2I aP, const SEG& aLine ); - ///< Produce a meander shape of given type. SHAPE_LINE_CHAIN genMeanderShape( VECTOR2D aP, VECTOR2D aDir, bool aSide, MEANDER_TYPE aType, int aAmpl, int aBaselineOffset = 0 );