Pcbnew: handle connected copper circle points

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/18774
This commit is contained in:
John Beard 2024-09-25 06:31:21 +01:00
parent 8128f4ebd9
commit aea42a5cdf
4 changed files with 60 additions and 24 deletions

View File

@ -41,10 +41,12 @@
#include <geometry/direction45.h>
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<TYPED_POINT2I> GetCircleKeyPoints( const CIRCLE& aCircle, bool aIncludeCenter );
} // namespace KIGEOM

View File

@ -23,9 +23,11 @@
#include "geometry/shape_utils.h"
#include <geometry/circle.h>
#include <geometry/seg.h>
#include <geometry/half_line.h>
#include <geometry/line.h>
#include <geometry/point_types.h>
#include <geometry/shape_rect.h>
@ -251,3 +253,27 @@ VECTOR2I KIGEOM::GetPoint( const SHAPE_RECT& aRect, DIRECTION_45::Directions aDi
}
return VECTOR2I();
}
std::vector<TYPED_POINT2I> KIGEOM::GetCircleKeyPoints( const CIRCLE& aCircle, bool aIncludeCenter )
{
std::vector<TYPED_POINT2I> 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;
}

View File

@ -37,7 +37,10 @@
#include <lset.h>
#include <pad.h>
#include <base_units.h>
#include <geometry/shape_circle.h>
#include <geometry/shape_compound.h>
#include <geometry/point_types.h>
#include <geometry/shape_utils.h>
#include <pcb_shape.h>
#include <pcb_painter.h>
#include <api/board/board_types.pb.h>
@ -336,6 +339,15 @@ std::vector<VECTOR2I> 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<VECTOR2I> PCB_SHAPE::GetConnectionPoints() const
break;
default:
case SHAPE_T::UNDEFINED:
// No default - handle all cases, even if just break
break;
}

View File

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