Browse Source

Pcbnew: handle connected copper circle points

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/18774
jobs
John Beard 1 year ago
parent
commit
aea42a5cdf
  1. 11
      libs/kimath/include/geometry/shape_utils.h
  2. 26
      libs/kimath/src/geometry/shape_utils.cpp
  3. 15
      pcbnew/pcb_shape.cpp
  4. 32
      pcbnew/tools/pcb_grid_helper.cpp

11
libs/kimath/include/geometry/shape_utils.h

@ -41,10 +41,12 @@
#include <geometry/direction45.h> #include <geometry/direction45.h>
class CIRCLE;
class HALF_LINE; class HALF_LINE;
class LINE; class LINE;
class SEG; class SEG;
class SHAPE_RECT; class SHAPE_RECT;
struct TYPED_POINT2I;
namespace KIGEOM 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 ); 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 } // namespace KIGEOM

26
libs/kimath/src/geometry/shape_utils.cpp

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

15
pcbnew/pcb_shape.cpp

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

32
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_CENTER | KIGEOM::OVAL_CAP_TIPS | KIGEOM::OVAL_SIDE_MIDPOINTS
| KIGEOM::OVAL_CARDINAL_EXTREMES; | 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 ) auto handlePadShape = [&]( PAD* aPad )
{ {
addAnchor( aPad->GetPosition(), ORIGIN | SNAPPABLE, aPad, POINT_TYPE::PT_CENTER ); 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() ) switch( aPad->GetShape() )
{ {
case PAD_SHAPE::CIRCLE: 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; break;
}
case PAD_SHAPE::OVAL: case PAD_SHAPE::OVAL:
{ {
const OVAL oval( aPad->GetSize(), aPad->GetPosition(), aPad->GetOrientation() ); 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 ) if( hole_size.x == hole_size.y )
{ {
// Circle // 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 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 // 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: // same as the pad. In future, this may not be true:
// https://gitlab.com/kicad/code/kicad/-/issues/4124 // 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 ); snap_pts = KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags );
} }
for( const TYPED_POINT2I& snap_pt : snap_pts ) 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 );
} }
}; };

Loading…
Cancel
Save