diff --git a/libs/kimath/include/geometry/shape_utils.h b/libs/kimath/include/geometry/shape_utils.h index 1d3a8e5dec..6055dd8716 100644 --- a/libs/kimath/include/geometry/shape_utils.h +++ b/libs/kimath/include/geometry/shape_utils.h @@ -41,10 +41,12 @@ #include +class CIRCLE; class HALF_LINE; class LINE; class SEG; class SHAPE_RECT; +struct TYPED_POINT2I; namespace KIGEOM { @@ -118,4 +120,13 @@ SHAPE_ARC MakeArcCw180( const VECTOR2I& aCenter, int aRadius, DIRECTION_45::Dire */ VECTOR2I GetPoint( const SHAPE_RECT& aRect, DIRECTION_45::Directions aDir ); + +/** + * Get key points of an CIRCLE. + * + * - The four cardinal points + * - Optionally the center + */ +std::vector GetCircleKeyPoints( const CIRCLE& aCircle, bool aIncludeCenter ); + } // namespace KIGEOM \ No newline at end of file diff --git a/libs/kimath/src/geometry/shape_utils.cpp b/libs/kimath/src/geometry/shape_utils.cpp index 106f26c174..3dbff90e48 100644 --- a/libs/kimath/src/geometry/shape_utils.cpp +++ b/libs/kimath/src/geometry/shape_utils.cpp @@ -23,9 +23,11 @@ #include "geometry/shape_utils.h" +#include #include #include #include +#include #include @@ -251,3 +253,27 @@ VECTOR2I KIGEOM::GetPoint( const SHAPE_RECT& aRect, DIRECTION_45::Directions aDi } return VECTOR2I(); } + + +std::vector KIGEOM::GetCircleKeyPoints( const CIRCLE& aCircle, bool aIncludeCenter ) +{ + std::vector pts; + + if( aIncludeCenter ) + { + pts.emplace_back( VECTOR2I{ 0, 0 }, POINT_TYPE::PT_CENTER ); + } + + pts.emplace_back( VECTOR2I{ 0, aCircle.Radius }, POINT_TYPE::PT_QUADRANT ); + pts.emplace_back( VECTOR2I{ aCircle.Radius, 0 }, POINT_TYPE::PT_QUADRANT ); + pts.emplace_back( VECTOR2I{ 0, -aCircle.Radius }, POINT_TYPE::PT_QUADRANT ); + pts.emplace_back( VECTOR2I{ -aCircle.Radius, 0 }, POINT_TYPE::PT_QUADRANT ); + + // Shift the points to the circle center + for( TYPED_POINT2I& pt : pts ) + { + pt.m_point += aCircle.Center; + } + + return pts; +} \ No newline at end of file diff --git a/pcbnew/pcb_shape.cpp b/pcbnew/pcb_shape.cpp index 0c79736237..b8d044f7aa 100644 --- a/pcbnew/pcb_shape.cpp +++ b/pcbnew/pcb_shape.cpp @@ -37,7 +37,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -336,6 +339,15 @@ std::vector PCB_SHAPE::GetConnectionPoints() const switch( m_shape ) { + case SHAPE_T::CIRCLE: + { + const CIRCLE circle( GetCenter(), GetRadius() ); + for( const TYPED_POINT2I& pt : KIGEOM::GetCircleKeyPoints( circle, false ) ) + { + ret.emplace_back( pt.m_point ); + } + break; + } case SHAPE_T::ARC: ret.emplace_back( GetArcMid() ); KI_FALLTHROUGH; @@ -358,7 +370,8 @@ std::vector PCB_SHAPE::GetConnectionPoints() const break; - default: + case SHAPE_T::UNDEFINED: + // No default - handle all cases, even if just break break; } diff --git a/pcbnew/tools/pcb_grid_helper.cpp b/pcbnew/tools/pcb_grid_helper.cpp index 76c8df842e..b86e40244b 100644 --- a/pcbnew/tools/pcb_grid_helper.cpp +++ b/pcbnew/tools/pcb_grid_helper.cpp @@ -1057,22 +1057,6 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos KIGEOM::OVAL_CENTER | KIGEOM::OVAL_CAP_TIPS | KIGEOM::OVAL_SIDE_MIDPOINTS | KIGEOM::OVAL_CARDINAL_EXTREMES; - // The key points of a circle centred around (0, 0) with the given radius - auto getCircleKeyPoints = []( int radius, bool aIncludeCenter ) - { - std::vector points = { - { { -radius, 0 }, POINT_TYPE::PT_QUADRANT }, - { { radius, 0 }, POINT_TYPE::PT_QUADRANT }, - { { 0, -radius }, POINT_TYPE::PT_QUADRANT }, - { { 0, radius }, POINT_TYPE::PT_QUADRANT }, - }; - - if( aIncludeCenter ) - points.push_back( { { 0, 0 }, POINT_TYPE::PT_CENTER } ); - - return points; - }; - auto handlePadShape = [&]( PAD* aPad ) { addAnchor( aPad->GetPosition(), ORIGIN | SNAPPABLE, aPad, POINT_TYPE::PT_CENTER ); @@ -1084,14 +1068,15 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos switch( aPad->GetShape() ) { case PAD_SHAPE::CIRCLE: - for( const TYPED_POINT2I& pt : getCircleKeyPoints( aPad->GetSizeX() / 2, false ) ) + { + const CIRCLE circle( aPad->ShapePos(), aPad->GetSizeX() / 2 ); + for( const TYPED_POINT2I& pt : KIGEOM::GetCircleKeyPoints( circle, false ) ) { - // Transform to the pad positon - addAnchor( aPad->ShapePos() + pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types ); + addAnchor( pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types ); } break; - + } case PAD_SHAPE::OVAL: { const OVAL oval( aPad->GetSize(), aPad->GetPosition(), aPad->GetOrientation() ); @@ -1162,7 +1147,8 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos if( hole_size.x == hole_size.y ) { // Circle - snap_pts = getCircleKeyPoints( hole_size.x / 2, true ); + const CIRCLE circle( hole_pos, hole_size.x / 2 ); + snap_pts = KIGEOM::GetCircleKeyPoints( circle, true ); } else { @@ -1171,12 +1157,12 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos // For now there's no way to have an off-angle hole, so this is the // same as the pad. In future, this may not be true: // https://gitlab.com/kicad/code/kicad/-/issues/4124 - const OVAL oval( hole_size, { 0, 0 }, aPad->GetOrientation() ); + const OVAL oval( hole_size, hole_pos, aPad->GetOrientation() ); snap_pts = KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags ); } for( const TYPED_POINT2I& snap_pt : snap_pts ) - addAnchor( hole_pos + snap_pt.m_point, OUTLINE | SNAPPABLE, aPad, snap_pt.m_types ); + addAnchor( snap_pt.m_point, OUTLINE | SNAPPABLE, aPad, snap_pt.m_types ); } };