mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-13 17:53:11 +02:00
Geom: use SHAPE_SEGMENT for OVAL
OVAL didn't do anything SHAPE_SEGMENT couldn't already do.
This commit is contained in:
parent
60a5c8b742
commit
1e272ca21b
@ -25,86 +25,22 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <math/box2.h>
|
||||
#include <math/vector2d.h>
|
||||
#include <geometry/approximation.h>
|
||||
#include <geometry/eda_angle.h>
|
||||
#include <geometry/point_types.h>
|
||||
#include <geometry/seg.h>
|
||||
|
||||
|
||||
class SHAPE_LINE_CHAIN;
|
||||
#include <geometry/shape_segment.h>
|
||||
|
||||
/**
|
||||
* Class that represents an oval shape (rectangle with semicircular end caps)
|
||||
* @file Utility functions for ovals (oblongs/stadiums)
|
||||
*
|
||||
* This is not a full-blown SHAPE (yet), but can be used for some simple
|
||||
* purposes, as well as for type-based logic.
|
||||
* An "oval" is represented by SHAPE_SEGMENT, but these functions
|
||||
* aren't required for most users of SHAPE_SEGMENT.
|
||||
*/
|
||||
class OVAL
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create an oval from the segment joining the centers of the semicircles
|
||||
* and the diameter of the semicircles.
|
||||
*/
|
||||
OVAL( const SEG& aSeg, int aWidth );
|
||||
|
||||
/**
|
||||
* Create an oval from the overall size, the center of the oval, and the rotation.
|
||||
*
|
||||
* The shorter dimension is the width of the semicircles.
|
||||
*/
|
||||
OVAL( const VECTOR2I& aOverallSize, const VECTOR2I& aCenter, const EDA_ANGLE& aRotation );
|
||||
|
||||
/**
|
||||
* Get the bounding box of the oval
|
||||
*/
|
||||
BOX2I BBox( int aClearance ) const;
|
||||
|
||||
/**
|
||||
* Get the width of the oval (diameter of the semicircles)
|
||||
*/
|
||||
int GetWidth() const { return m_width; }
|
||||
|
||||
/**
|
||||
* Get the overall length of the oval from endcap tip to endcap tip
|
||||
*/
|
||||
int GetLength() const { return m_seg.Length() + m_width; }
|
||||
|
||||
/**
|
||||
* Get the side length of the oval (=length between the centers of the semicircles)
|
||||
*/
|
||||
int GetSideLength() const { return m_seg.Length(); }
|
||||
|
||||
/**
|
||||
* Get the center point of the oval.
|
||||
*/
|
||||
VECTOR2I GetCenter() const { return m_seg.Center(); }
|
||||
|
||||
/**
|
||||
* Get the central segment of the oval
|
||||
*
|
||||
* (Endpoint are the centers of the semicircles)
|
||||
*/
|
||||
const SEG& GetSegment() const { return m_seg; }
|
||||
|
||||
/**
|
||||
* Get the angle of the oval's central segment.
|
||||
*
|
||||
* The direction is aligned with the segment start/end
|
||||
*/
|
||||
EDA_ANGLE GetAngle() const { return EDA_ANGLE( m_seg.B - m_seg.A ); }
|
||||
|
||||
private:
|
||||
SEG m_seg;
|
||||
int m_width;
|
||||
};
|
||||
class SHAPE_LINE_CHAIN;
|
||||
|
||||
namespace KIGEOM
|
||||
{
|
||||
|
||||
SHAPE_LINE_CHAIN ConvertToChain( const OVAL& aOval );
|
||||
SHAPE_LINE_CHAIN ConvertToChain( const SHAPE_SEGMENT& aOval );
|
||||
|
||||
|
||||
enum OVAL_KEY_POINTS
|
||||
@ -129,12 +65,11 @@ using OVAL_KEY_POINT_FLAGS = unsigned int;
|
||||
* - The tips of the end caps
|
||||
* - The extreme cardinal points of the whole oval (if rotated non-cardinally)
|
||||
*
|
||||
* @param aOvalSize - The size of the oval (overall length and width)
|
||||
* @param aRotation - The rotation of the oval
|
||||
* @param aOval - The oval to get the points from
|
||||
* @param aFlags - The flags indicating which points to return
|
||||
*
|
||||
* @return std::vector<TYPED_POINT2I> - The list of points and their geomtrical types
|
||||
*/
|
||||
std::vector<TYPED_POINT2I> GetOvalKeyPoints( const OVAL& aOval, OVAL_KEY_POINT_FLAGS aFlags );
|
||||
std::vector<TYPED_POINT2I> GetOvalKeyPoints( const SHAPE_SEGMENT& aOval, OVAL_KEY_POINT_FLAGS aFlags );
|
||||
|
||||
} // namespace KIGEOM
|
||||
} // namespace KIGEOM
|
||||
|
@ -54,6 +54,8 @@ public:
|
||||
m_width( aWidth )
|
||||
{};
|
||||
|
||||
static SHAPE_SEGMENT BySizeAndCenter( const VECTOR2I& aSize, const VECTOR2I& aCenter, const EDA_ANGLE& aRotation );
|
||||
|
||||
~SHAPE_SEGMENT() {};
|
||||
|
||||
SHAPE* Clone() const override
|
||||
@ -140,6 +142,24 @@ public:
|
||||
return m_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total length of the segment, from tip to tip.
|
||||
*/
|
||||
int GetTotalLength() const
|
||||
{
|
||||
return m_seg.Length() + m_width;
|
||||
}
|
||||
|
||||
VECTOR2I GetCenter() const
|
||||
{
|
||||
return m_seg.Center();
|
||||
}
|
||||
|
||||
EDA_ANGLE GetAngle() const
|
||||
{
|
||||
return EDA_ANGLE( m_seg.B - m_seg.A );
|
||||
}
|
||||
|
||||
bool IsSolid() const override
|
||||
{
|
||||
return true;
|
||||
|
@ -27,48 +27,14 @@
|
||||
|
||||
#include <trigo.h> // for RotatePoint
|
||||
#include <geometry/shape_arc.h>
|
||||
#include <geometry/shape_circle.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
|
||||
using namespace KIGEOM;
|
||||
|
||||
OVAL::OVAL( const SEG& aSeg, int aWidth ) : m_seg( aSeg ), m_width( aWidth )
|
||||
|
||||
SHAPE_LINE_CHAIN KIGEOM::ConvertToChain( const SHAPE_SEGMENT& aOval )
|
||||
{
|
||||
// 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 SEG& seg = aOval.GetSeg();
|
||||
const VECTOR2I perp = GetRotated( seg.B - seg.A, ANGLE_90 ).Resize( aOval.GetWidth() / 2 );
|
||||
|
||||
SHAPE_LINE_CHAIN chain;
|
||||
@ -81,11 +47,10 @@ SHAPE_LINE_CHAIN KIGEOM::ConvertToChain( const OVAL& aOval )
|
||||
}
|
||||
|
||||
|
||||
std::vector<TYPED_POINT2I> KIGEOM::GetOvalKeyPoints( const OVAL& aOval,
|
||||
OVAL_KEY_POINT_FLAGS aFlags )
|
||||
std::vector<TYPED_POINT2I> KIGEOM::GetOvalKeyPoints( const SHAPE_SEGMENT& aOval, OVAL_KEY_POINT_FLAGS aFlags )
|
||||
{
|
||||
const int half_width = aOval.GetWidth() / 2;
|
||||
const int half_len = aOval.GetLength() / 2;
|
||||
const int half_len = aOval.GetTotalLength() / 2;
|
||||
const EDA_ANGLE rotation = aOval.GetAngle() - ANGLE_90;
|
||||
|
||||
// Points on a non-rotated pad at the origin, long-axis is y
|
||||
@ -194,4 +159,4 @@ std::vector<TYPED_POINT2I> KIGEOM::GetOvalKeyPoints( const OVAL& aOval,
|
||||
}
|
||||
|
||||
return pts;
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,31 @@
|
||||
#include <geometry/shape_circle.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
|
||||
|
||||
SHAPE_SEGMENT SHAPE_SEGMENT::BySizeAndCenter( const VECTOR2I& aOverallSize, const VECTOR2I& aCenter,
|
||||
const EDA_ANGLE& aRotation )
|
||||
{
|
||||
VECTOR2I segVec{ 0, 0 };
|
||||
int width;
|
||||
|
||||
// Find the major axis, without endcaps
|
||||
if( aOverallSize.x > aOverallSize.y )
|
||||
{
|
||||
width = aOverallSize.y;
|
||||
segVec.x = aOverallSize.x - width;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = aOverallSize.x;
|
||||
segVec.y = aOverallSize.y - width;
|
||||
}
|
||||
|
||||
RotatePoint( segVec, aRotation );
|
||||
|
||||
return SHAPE_SEGMENT( aCenter - segVec / 2, aCenter + segVec / 2, width );
|
||||
}
|
||||
|
||||
|
||||
const std::string SHAPE_SEGMENT::Format( bool aCplusPlus ) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
@ -933,7 +933,7 @@ void OUTSET_ROUTINE::ProcessItem( BOARD_ITEM& aItem )
|
||||
|
||||
if( m_params.roundCorners )
|
||||
{
|
||||
const OVAL oval( seg, m_params.outsetDistance * 2 );
|
||||
const SHAPE_SEGMENT oval( seg, m_params.outsetDistance * 2 );
|
||||
addChain( KIGEOM::ConvertToChain( oval ) );
|
||||
}
|
||||
else
|
||||
|
@ -1204,7 +1204,8 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
|
||||
}
|
||||
case PAD_SHAPE::OVAL:
|
||||
{
|
||||
const OVAL oval( aPad->GetSize( aLayer ), aPad->GetPosition(), aPad->GetOrientation() );
|
||||
const SHAPE_SEGMENT oval = SHAPE_SEGMENT::BySizeAndCenter(
|
||||
aPad->GetSize( aLayer ), aPad->GetPosition(), aPad->GetOrientation() );
|
||||
|
||||
for( const TYPED_POINT2I& pt : KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags ) )
|
||||
addAnchor( pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types );
|
||||
@ -1281,7 +1282,8 @@ 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, hole_pos, aPad->GetOrientation() );
|
||||
const SHAPE_SEGMENT oval =
|
||||
SHAPE_SEGMENT::BySizeAndCenter( hole_size, hole_pos, aPad->GetOrientation() );
|
||||
snap_pts = KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags );
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ BOOST_AUTO_TEST_SUITE( Oval )
|
||||
|
||||
struct OVAL_POINTS_TEST_CASE
|
||||
{
|
||||
OVAL m_oval;
|
||||
SHAPE_SEGMENT m_oval;
|
||||
std::vector<TYPED_POINT2I> m_expected_points;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user