7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-20 00:21:31 +00:00

Multichannel: split out some geometric routines

Putting them somewhere in the geom utils means they
can be reused, and also tested if needed.
This commit is contained in:
John Beard 2024-11-08 19:40:57 +08:00
parent 6a96c16c2c
commit df933df416
3 changed files with 71 additions and 28 deletions
libs/kimath
include/geometry
src/geometry
pcbnew/tools

View File

@ -75,6 +75,11 @@ OPT_VECTOR2I GetSharedEndpoint( const SEG& aSegA, const SEG& aSegB );
*/
std::array<SEG, 4> BoxToSegs( const BOX2I& aBox );
/**
* Add the 4 corners of a BOX2I to a vector.
*/
void CollectBoxCorners( const BOX2I& aBox, std::vector<VECTOR2I>& aCorners );
/**
* Get the segments of a box that are in the given direction.
*
@ -142,4 +147,19 @@ VECTOR2I GetPoint( const SHAPE_RECT& aRect, DIRECTION_45::Directions aDir, int a
*/
std::vector<TYPED_POINT2I> GetCircleKeyPoints( const CIRCLE& aCircle, bool aIncludeCenter );
/*
* Take a polygon and 'rectify' it, so that all sides are H/V.
*
* The entire original polygon is contained within the new one.
* The new polygon will pass though each original corner,
* but it can have additional corners, or corners can be simplified away.
*
* E.g.:
* ____ _______
* / \___ -> | |___
* |________\ |_________|
*/
SHAPE_LINE_CHAIN RectifyPolygon( const SHAPE_LINE_CHAIN& aPoly );
} // namespace KIGEOM

View File

@ -80,6 +80,15 @@ std::array<SEG, 4> KIGEOM::BoxToSegs( const BOX2I& aBox )
}
void KIGEOM::CollectBoxCorners( const BOX2I& aBox, std::vector<VECTOR2I>& aCorners )
{
aCorners.push_back( { aBox.GetLeft(), aBox.GetTop() } );
aCorners.push_back( { aBox.GetRight(), aBox.GetTop() } );
aCorners.push_back( { aBox.GetRight(), aBox.GetBottom() } );
aCorners.push_back( { aBox.GetLeft(), aBox.GetBottom() } );
}
std::vector<SEG> KIGEOM::GetSegsInDirection( const BOX2I& aBox, DIRECTION_45::Directions aDir )
{
// clang-format off
@ -332,4 +341,38 @@ std::vector<TYPED_POINT2I> KIGEOM::GetCircleKeyPoints( const CIRCLE& aCircle, bo
}
return pts;
}
SHAPE_LINE_CHAIN KIGEOM::RectifyPolygon( const SHAPE_LINE_CHAIN& aPoly )
{
SHAPE_LINE_CHAIN raOutline;
const auto handleSegment = [&]( const SEG& aSeg )
{
const VECTOR2I p0( aSeg.A.x, aSeg.B.y );
const VECTOR2I p1( aSeg.B.x, aSeg.A.y );
raOutline.Append( aSeg.A );
if( !aPoly.PointInside( p0 ) )
raOutline.Append( p0 );
else
raOutline.Append( p1 );
};
for( int i = 0; i < aPoly.SegmentCount(); i++ )
{
handleSegment( aPoly.CSegment( i ) );
}
// Manually handle the last segment if not closed
if( !aPoly.IsClosed() )
{
handleSegment( SEG( aPoly.CPoint( -1 ), aPoly.CPoint( 0 ) ) );
}
raOutline.SetClosed( true );
raOutline.Simplify();
return raOutline;
}

View File

@ -34,6 +34,7 @@
#include <zone.h>
#include <geometry/convex_hull.h>
#include <geometry/shape_utils.h>
#include <pcb_group.h>
#include <connectivity/connectivity_data.h>
#include <connectivity/topo_match.h>
@ -168,43 +169,22 @@ MULTICHANNEL_TOOL::queryComponentsInComponentClass( const wxString& aComponentCl
const SHAPE_LINE_CHAIN MULTICHANNEL_TOOL::buildRAOutline( std::set<FOOTPRINT*>& aFootprints,
int aMargin )
{
std::vector<VECTOR2I> bbCorners, hullVertices;
std::vector<VECTOR2I> bbCorners;
bbCorners.reserve( aFootprints.size() * 4 );
for( auto fp : aFootprints )
{
auto bb = fp->GetBoundingBox( false );
bb.Inflate( aMargin );
bbCorners.push_back( VECTOR2I( bb.GetX(), bb.GetY() ) );
bbCorners.push_back( VECTOR2I( bb.GetX() + bb.GetWidth(), bb.GetY() ) );
bbCorners.push_back( VECTOR2I( bb.GetX() + bb.GetWidth(), bb.GetY() + bb.GetHeight() ) );
bbCorners.push_back( VECTOR2I( bb.GetX(), bb.GetY() + bb.GetHeight() ) );
const BOX2I bb = fp->GetBoundingBox( false ).GetInflated( aMargin );
KIGEOM::CollectBoxCorners( bb, bbCorners );
}
std::vector<VECTOR2I> hullVertices;
BuildConvexHull( hullVertices, bbCorners );
SHAPE_LINE_CHAIN hull( hullVertices );
SHAPE_LINE_CHAIN raOutline;
// make the newly computed convex hull use only 90 degree segments
hull.SetClosed( true );
for( int i = 0; i < hull.SegmentCount(); i++ )
{
const auto& seg = hull.CSegment( i );
const VECTOR2I p0( seg.A.x, seg.B.y );
const VECTOR2I p1( seg.B.x, seg.A.y );
raOutline.Append( seg.A );
if( !hull.PointInside( p0 ) )
raOutline.Append( p0 );
else
raOutline.Append( p1 );
}
raOutline.SetClosed( true );
raOutline.Simplify();
return raOutline;
// Make the newly computed convex hull use only 90 degree segments
return KIGEOM::RectifyPolygon( hull );
}