@ -26,20 +26,72 @@
# include "geometry/oval.h"
# include <trigo.h> // for RotatePoint
# include <geometry/shape_arc.h>
# include <geometry/shape_circle.h>
# include <geometry/shape_line_chain.h>
using namespace KIGEOM ;
std : : vector < TYPED_POINT2I > GetOvalKeyPoints ( const VECTOR2I & aOvalSize , const EDA_ANGLE & aRotation ,
OVAL_KEY_POINT_FLAGS aFlags )
OVAL : : OVAL ( const SEG & aSeg , int aWidth ) : m_seg ( aSeg ) , m_width ( aWidth )
{
const VECTOR2I half_size = aOvalSize / 2 ;
const int half_width = std : : min ( half_size . x , half_size . y ) ;
const int half_len = std : : max ( half_size . x , half_size . y ) ;
// A negative width is meaningless
wxASSERT ( aWidth > 0 ) ;
}
OVAL : : OVAL ( const VECTOR2I & aOverallSize , const VECTOR2I & aCenter , const EDA_ANGLE & aRotation )
{
VECTOR2I segVec { } ;
// Find the major axis, without endcaps
if ( aOverallSize . x > aOverallSize . y )
segVec . x = ( aOverallSize . x - aOverallSize . y ) ;
else
segVec . y = ( aOverallSize . y - aOverallSize . x ) ;
RotatePoint ( segVec , aRotation ) ;
m_seg = SEG ( aCenter - segVec / 2 , aCenter + segVec / 2 ) ;
m_width = std : : min ( aOverallSize . x , aOverallSize . y ) ;
}
BOX2I OVAL : : BBox ( int aClearance ) const
{
const int rad = m_width / 2 + aClearance ;
const VECTOR2I & topleft = LexicographicalMin ( m_seg . A , m_seg . B ) ;
const VECTOR2I & bottomright = LexicographicalMax ( m_seg . A , m_seg . B ) ;
return BOX2I : : ByCorners ( topleft - VECTOR2I ( rad , rad ) , bottomright + VECTOR2I ( rad , rad ) ) ;
}
SHAPE_LINE_CHAIN KIGEOM : : ConvertToChain ( const OVAL & aOval )
{
const SEG & seg = aOval . GetSegment ( ) ;
const VECTOR2I perp = GetRotated ( seg . B - seg . A , ANGLE_90 ) . Resize ( aOval . GetWidth ( ) / 2 ) ;
SHAPE_LINE_CHAIN chain ;
chain . Append ( seg . A - perp ) ;
chain . Append ( SHAPE_ARC ( seg . A , seg . A - perp , ANGLE_180 ) ) ;
chain . Append ( seg . B + perp ) ;
chain . Append ( SHAPE_ARC ( seg . B , seg . B + perp , ANGLE_180 ) ) ;
return chain ;
}
std : : vector < TYPED_POINT2I > KIGEOM : : GetOvalKeyPoints ( const OVAL & aOval ,
OVAL_KEY_POINT_FLAGS aFlags )
{
const int half_width = aOval . GetWidth ( ) / 2 ;
const int half_len = aOval . GetLength ( ) / 2 ;
const EDA_ANGLE rotation = aOval . GetAngle ( ) - ANGLE_90 ;
// Points on a non-rotated pad at the origin, long-axis is y
// (so for now, width is left/right, len is up/down)
std : : vector < TYPED_POINT2I > pts ;
if ( aFlags & OVAL_CENTER )
if ( aFlags & OVAL_CENTER )
{
// Centre is easy
pts . emplace_back ( VECTOR2I { 0 , 0 } , POINT_TYPE : : PT_CENTER ) ;
@ -55,7 +107,7 @@ std::vector<TYPED_POINT2I> GetOvalKeyPoints( const VECTOR2I& aOvalSize, const ED
if ( aFlags & OVAL_CAP_TIPS )
{
// If the oval is square-on, the tips are quadrants
const POINT_TYPE pt_type = aR otation. IsCardinal ( ) ? PT_QUADRANT : PT_END ;
const POINT_TYPE pt_type = r otation. IsCardinal ( ) ? PT_QUADRANT : PT_END ;
// Cap ends
pts . emplace_back ( VECTOR2I { 0 , half_len } , pt_type ) ;
@ -65,14 +117,14 @@ std::vector<TYPED_POINT2I> GetOvalKeyPoints( const VECTOR2I& aOvalSize, const ED
// Distance from centre to cap centres
const int d_centre_to_cap_centre = half_len - half_width ;
if ( aFlags & OVAL_CAP_CENTERS )
if ( aFlags & OVAL_CAP_CENTERS )
{
// Cap centres
pts . emplace_back ( VECTOR2I { 0 , d_centre_to_cap_centre } , POINT_TYPE : : PT_CENTER ) ;
pts . emplace_back ( VECTOR2I { 0 , - d_centre_to_cap_centre } , POINT_TYPE : : PT_CENTER ) ;
}
if ( aFlags & OVAL_SIDE_ENDS )
if ( aFlags & OVAL_SIDE_ENDS )
{
const auto add_end = [ & ] ( const VECTOR2I & aPt )
{
@ -86,11 +138,6 @@ std::vector<TYPED_POINT2I> GetOvalKeyPoints( const VECTOR2I& aOvalSize, const ED
add_end ( { - half_width , - d_centre_to_cap_centre } ) ;
}
// If the pad is horizontal (i.e. x > y), we'll rotate the whole thing
// 90 degrees and work with it as if it was vertical
const bool swap_xy = half_size . x > half_size . y ;
const EDA_ANGLE rotation = aRotation + ( swap_xy ? - ANGLE_90 : ANGLE_0 ) ;
// Add the quadrant points to the caps only if rotated
// (otherwise they're just the tips)
if ( ( aFlags & OVAL_CARDINAL_EXTREMES ) & & ! rotation . IsCardinal ( ) )
@ -108,7 +155,7 @@ std::vector<TYPED_POINT2I> GetOvalKeyPoints( const VECTOR2I& aOvalSize, const ED
// Rotate in the opposite direction to the oval's rotation
// (that will be unwound later)
EDA_ANGLE radial_line_rotation = - rotation ;
EDA_ANGLE radial_line_rotation = rotation ;
radial_line_rotation . Normalize90 ( ) ;
@ -139,8 +186,10 @@ std::vector<TYPED_POINT2I> GetOvalKeyPoints( const VECTOR2I& aOvalSize, const ED
for ( TYPED_POINT2I & pt : pts )
{
// Transform to the actual orientation
// Already includes the extra 90 to swap x/y if needed
RotatePoint ( pt . m_point , rotation ) ;
RotatePoint ( pt . m_point , - rotation ) ;
// Translate to the actual position
pt . m_point + = aOval . GetCenter ( ) ;
}
return pts ;