Allow SHAPE_LINE_CHAIN and SHAPE_ARC to be mirrored using a SEG

This commit is contained in:
Thomas Pointhuber 2021-04-11 14:28:32 +02:00 committed by Jon Evans
parent fe8fbf1d5d
commit a30894e5a1
7 changed files with 54 additions and 24 deletions

View File

@ -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<VECTOR2I::extended_type>( d.x ), l_squared );
c.y = A.y + rescale( t, static_cast<VECTOR2I::extended_type>( d.y ), l_squared );
}
return 2 * c - aP;
}
inline std::ostream& operator<<( std::ostream& aStream, const SEG& aSeg )
{
aStream << "[ " << aSeg.A << " - " << aSeg.B << " ]";

View File

@ -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;

View File

@ -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

View File

@ -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 );

View File

@ -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 )

View File

@ -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;

View File

@ -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 );