Clip the leader lines properly when using circular text frame
Fixes https://gitlab.com/kicad/code/kicad/issues/7810
This commit is contained in:
parent
720147d272
commit
0f22b54cd8
|
@ -76,7 +76,7 @@ public:
|
|||
*
|
||||
* Computes the intersection points between this circle and aCircle.
|
||||
*
|
||||
* @param aCircle The other circle to intersect with this.
|
||||
* @param aCircle The other circle to intersect with this
|
||||
* @return std::vector containing:
|
||||
* - 0 elements if the circles do not intersect
|
||||
* - 1 element if the circles are tangent
|
||||
|
@ -87,6 +87,16 @@ public:
|
|||
/**
|
||||
* Function Intersect()
|
||||
*
|
||||
* Computes the intersection points between this circle and aSeg.
|
||||
*
|
||||
* @param aSeg The segment to intersect with this circle (end points ignored)
|
||||
* @return std::vector containing up to two intersection points
|
||||
*/
|
||||
std::vector<VECTOR2I> Intersect( const SEG& aSeg ) const;
|
||||
|
||||
/**
|
||||
* Function IntersectLine()
|
||||
*
|
||||
* Computes the intersection points between this circle and aLine.
|
||||
*
|
||||
* @param aLine The line to intersect with this circle (end points ignored)
|
||||
|
@ -95,7 +105,17 @@ public:
|
|||
* - 1 element if the line is tangent to the circle
|
||||
* - 2 elements if the line intersects the circle
|
||||
*/
|
||||
std::vector<VECTOR2I> Intersect( const SEG& aLine ) const;
|
||||
std::vector<VECTOR2I> IntersectLine( const SEG& aLine ) const;
|
||||
|
||||
/**
|
||||
* Function Contains()
|
||||
*
|
||||
* Checks whether point aP is inside this circle.
|
||||
*
|
||||
* @param aP The point to check
|
||||
* @return true if the point is inside, false otherwise
|
||||
*/
|
||||
bool Contains( const VECTOR2I& aP );
|
||||
};
|
||||
|
||||
#endif // __CIRCLE_H
|
||||
|
|
|
@ -46,6 +46,11 @@ public:
|
|||
m_circle( aCenter, aRadius )
|
||||
{}
|
||||
|
||||
SHAPE_CIRCLE( const CIRCLE& aCircle ) :
|
||||
SHAPE( SH_CIRCLE ),
|
||||
m_circle( aCircle )
|
||||
{}
|
||||
|
||||
SHAPE_CIRCLE( const SHAPE_CIRCLE& aOther ) :
|
||||
SHAPE( SH_CIRCLE ),
|
||||
m_circle( aOther.m_circle )
|
||||
|
|
|
@ -97,7 +97,7 @@ CIRCLE& CIRCLE::ConstructFromTanTanPt( const SEG& aLineA, const SEG& aLineB, con
|
|||
anglebisector = aLineA.ParallelSeg( midPt );
|
||||
|
||||
Center = aP; // use this circle as a construction to find the actual centers
|
||||
std::vector<VECTOR2I> possibleCenters = Intersect( anglebisector );
|
||||
std::vector<VECTOR2I> possibleCenters = IntersectLine( anglebisector );
|
||||
|
||||
wxCHECK_MSG( possibleCenters.size() > 0, *this, "No solutions exist!" );
|
||||
intersectPoint = aLineA.A; // just for the purpose of deciding which solution to return
|
||||
|
@ -138,7 +138,7 @@ CIRCLE& CIRCLE::ConstructFromTanTanPt( const SEG& aLineA, const SEG& aLineB, con
|
|||
|
||||
// Find the homothetic image of aP in the construction circle (hSolution)
|
||||
SEG throughaP( intersectPoint, aP );
|
||||
std::vector<VECTOR2I> hProjections = hSolution.Intersect( throughaP );
|
||||
std::vector<VECTOR2I> hProjections = hSolution.IntersectLine( throughaP );
|
||||
wxCHECK_MSG( hProjections.size() > 0, *this, "No solutions exist!" );
|
||||
|
||||
// We want to create a fillet, so the projection of homothetic projection of aP
|
||||
|
@ -257,7 +257,33 @@ std::vector<VECTOR2I> CIRCLE::Intersect( const CIRCLE& aCircle ) const
|
|||
}
|
||||
|
||||
|
||||
std::vector<VECTOR2I> CIRCLE::Intersect( const SEG& aLine ) const
|
||||
std::vector<VECTOR2I> CIRCLE::Intersect( const SEG& aSeg ) const
|
||||
{
|
||||
std::vector<VECTOR2I> retval;
|
||||
|
||||
for( VECTOR2I& intersection : IntersectLine( aSeg ) )
|
||||
{
|
||||
VECTOR2I delta = aSeg.B - aSeg.A;
|
||||
|
||||
if( delta.x > delta.y )
|
||||
{
|
||||
if( intersection.x >= std::min( aSeg.A.x, aSeg.B.x )
|
||||
&& intersection.x <= std::max( aSeg.A.x, aSeg.B.x ) )
|
||||
retval.push_back( intersection );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( intersection.y >= std::min( aSeg.A.y, aSeg.B.y )
|
||||
&& intersection.y <= std::max( aSeg.A.y, aSeg.B.y ) )
|
||||
retval.push_back( intersection );
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
std::vector<VECTOR2I> CIRCLE::IntersectLine( const SEG& aLine ) const
|
||||
{
|
||||
std::vector<VECTOR2I> retval;
|
||||
|
||||
|
@ -311,3 +337,8 @@ std::vector<VECTOR2I> CIRCLE::Intersect( const SEG& aLine ) const
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
bool CIRCLE::Contains( const VECTOR2I& aP )
|
||||
{
|
||||
return ( aP - Center ).EuclideanNorm() < Radius;
|
||||
}
|
||||
|
|
|
@ -476,6 +476,30 @@ OPT_VECTOR2I DIMENSION_BASE::segPolyIntersection( SHAPE_POLY_SET& aPoly, SEG& aS
|
|||
}
|
||||
|
||||
|
||||
OPT_VECTOR2I DIMENSION_BASE::segCircleIntersection( CIRCLE& aCircle, SEG& aSeg, bool aStart )
|
||||
{
|
||||
VECTOR2I start( aStart ? aSeg.A : aSeg.B );
|
||||
VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
|
||||
|
||||
if( aCircle.Contains( start ) )
|
||||
return NULLOPT;
|
||||
|
||||
std::vector<VECTOR2I> intersections = aCircle.Intersect( aSeg );
|
||||
|
||||
for( VECTOR2I& intersection : aCircle.Intersect( aSeg ) )
|
||||
{
|
||||
if( ( intersection - start ).SquaredEuclideanNorm() <
|
||||
( endpoint - start ).SquaredEuclideanNorm() )
|
||||
endpoint = intersection;
|
||||
}
|
||||
|
||||
if( start == endpoint )
|
||||
return NULLOPT;
|
||||
|
||||
return OPT_VECTOR2I( endpoint );
|
||||
}
|
||||
|
||||
|
||||
ALIGNED_DIMENSION::ALIGNED_DIMENSION( BOARD_ITEM* aParent, KICAD_T aType ) :
|
||||
DIMENSION_BASE( aParent, aType ),
|
||||
m_height( 0 )
|
||||
|
@ -886,13 +910,29 @@ void LEADER::updateGeometry()
|
|||
VECTOR2I start( m_start );
|
||||
start += firstLine.Resize( m_extensionOffset );
|
||||
|
||||
SEG primarySeg( m_start, m_end );
|
||||
OPT_VECTOR2I primaryEndpoint = segPolyIntersection( polyBox, primarySeg );
|
||||
SEG arrowSeg( m_start, m_end );
|
||||
SEG textSeg( m_end, m_text.GetPosition() );
|
||||
OPT_VECTOR2I arrowSegEnd, textSegEnd;
|
||||
|
||||
if( !primaryEndpoint )
|
||||
primaryEndpoint = m_end;
|
||||
if( m_textFrame == DIM_TEXT_FRAME::CIRCLE )
|
||||
{
|
||||
double penWidth = m_text.GetEffectiveTextPenWidth() / 2.0;
|
||||
double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
|
||||
CIRCLE circle( textBox.GetCenter(), radius );
|
||||
|
||||
m_shapes.emplace_back( new SHAPE_SEGMENT( start, *primaryEndpoint ) );
|
||||
arrowSegEnd = segCircleIntersection( circle, arrowSeg );
|
||||
textSegEnd = segCircleIntersection( circle, textSeg );
|
||||
}
|
||||
else
|
||||
{
|
||||
arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
|
||||
textSegEnd = segPolyIntersection( polyBox, textSeg );
|
||||
}
|
||||
|
||||
if( !arrowSegEnd )
|
||||
arrowSegEnd = m_end;
|
||||
|
||||
m_shapes.emplace_back( new SHAPE_SEGMENT( start, *arrowSegEnd ) );
|
||||
|
||||
// Add arrows
|
||||
VECTOR2I arrowEnd( m_arrowLength, 0 );
|
||||
|
@ -905,8 +945,6 @@ void LEADER::updateGeometry()
|
|||
m_shapes.emplace_back( new SHAPE_SEGMENT( start,
|
||||
start + wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
|
||||
|
||||
SEG textSeg( m_end, m_text.GetPosition() );
|
||||
OPT_VECTOR2I textEndpoint = segPolyIntersection( polyBox, textSeg );
|
||||
|
||||
if( !GetText().IsEmpty() )
|
||||
{
|
||||
|
@ -926,15 +964,6 @@ void LEADER::updateGeometry()
|
|||
double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
|
||||
m_shapes.emplace_back( new SHAPE_CIRCLE( textBox.GetCenter(), radius ) );
|
||||
|
||||
// Calculated bbox endpoint won't be right
|
||||
if( textEndpoint )
|
||||
{
|
||||
VECTOR2I totalLength( textBox.GetCenter() - m_end );
|
||||
VECTOR2I circleEndpoint( *textEndpoint - m_end );
|
||||
circleEndpoint = circleEndpoint.Resize( totalLength.EuclideanNorm() - radius );
|
||||
textEndpoint = OPT_VECTOR2I( VECTOR2I( m_end ) + circleEndpoint );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -943,8 +972,8 @@ void LEADER::updateGeometry()
|
|||
}
|
||||
}
|
||||
|
||||
if( textEndpoint && *primaryEndpoint == m_end )
|
||||
m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, *textEndpoint ) );
|
||||
if( textSegEnd && *arrowSegEnd == m_end )
|
||||
m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, *textSegEnd ) );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <board_item.h>
|
||||
#include <pcb_text.h>
|
||||
#include <geometry/shape.h>
|
||||
|
||||
#include <geometry/circle.h>
|
||||
|
||||
class LINE_READER;
|
||||
class MSG_PANEL_ITEM;
|
||||
|
@ -272,6 +272,7 @@ protected:
|
|||
* @return a point on aSeg that collides with aPoly closest to the start, if one exists
|
||||
*/
|
||||
static OPT_VECTOR2I segPolyIntersection( SHAPE_POLY_SET& aPoly, SEG& aSeg, bool aStart = true );
|
||||
static OPT_VECTOR2I segCircleIntersection( CIRCLE& aCircle, SEG& aSeg, bool aStart = true );
|
||||
|
||||
// Value format
|
||||
bool m_overrideTextEnabled; ///< Manually specify the displayed measurement value
|
||||
|
|
Loading…
Reference in New Issue