pcbnew: Retain 45° constraint

This also finishes the polygon with 45° lines when chosen as a create
option.

Fixes: lp:1833673
* https://bugs.launchpad.net/kicad/+bug/1833673
This commit is contained in:
Seth Hillbrand 2019-08-26 06:30:03 -07:00
parent a43a228f78
commit fccce265aa
6 changed files with 85 additions and 21 deletions

View File

@ -20,6 +20,7 @@
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <limits>
#include <preview_items/polygon_geom_manager.h>
@ -67,6 +68,7 @@ bool POLYGON_GEOM_MANAGER::AddPoint( const VECTOR2I& aPt )
void POLYGON_GEOM_MANAGER::SetFinished()
{
m_client.OnComplete( *this );
}
@ -144,16 +146,44 @@ void POLYGON_GEOM_MANAGER::updateLeaderPoints( const VECTOR2I& aEndPoint, LEADER
{
wxCHECK( m_lockedPoints.PointCount() > 0, /*void*/ );
const VECTOR2I& lastPt = m_lockedPoints.CLastPoint();
auto newEnd = VECTOR2I( aEndPoint );
if( m_leaderMode == LEADER_MODE::DEG45 || aModifier == LEADER_MODE::DEG45 )
{
const VECTOR2I lineVector( aEndPoint - lastPt );
// get a restricted 45/H/V line from the last fixed point to the cursor
newEnd = lastPt + GetVectorSnapped45( lineVector );
auto newEnd = lastPt + GetVectorSnapped45( lineVector );
SEG first( lastPt, newEnd );
SEG test_seg = m_lockedPoints.CSegment( 0 );
auto pt = first.IntersectLines( m_lockedPoints.CSegment( 0 ) );
int dist = pt ? ( aEndPoint - *pt ).EuclideanNorm() : std::numeric_limits<int>::max();
for( int i = 1; i < 8; i++ )
{
test_seg.B = ( test_seg.B - test_seg.A ).Rotate( M_PI_4 ) + test_seg.A;
auto pt2 = first.IntersectLines( test_seg );
if( pt2 )
{
int dist2 = ( aEndPoint - *pt2 ).EuclideanNorm();
if( dist2 < dist )
{
dist = dist2;
pt = pt2;
}
}
}
// direct segment
m_leaderPts = SHAPE_LINE_CHAIN( lastPt, newEnd );
if( pt )
m_leaderPts.Append( *pt );
}
else
{
// direct segment
m_leaderPts = SHAPE_LINE_CHAIN( lastPt, aEndPoint );
}
m_client.OnGeometryChange( *this );
}

View File

@ -95,6 +95,11 @@ public:
*/
void SetLeaderMode( LEADER_MODE aMode );
LEADER_MODE GetLeaderMode() const
{
return m_leaderMode;
}
/**
* Enables/disables self-intersecting polygons.
* @param aEnabled true if self-intersecting polygons are enabled.

View File

@ -36,30 +36,27 @@ bool EDIT_POINT::WithinPoint( const VECTOR2I& aPoint, unsigned int aSize ) const
}
EDIT_POINTS::EDIT_POINTS( EDA_ITEM* aParent ) :
EDA_ITEM( NOT_USED ), m_parent( aParent )
EDIT_POINTS::EDIT_POINTS( EDA_ITEM* aParent )
: EDA_ITEM( NOT_USED ), m_parent( aParent ), m_allowPoints( true )
{
}
EDIT_POINT* EDIT_POINTS::FindPoint( const VECTOR2I& aLocation, KIGFX::VIEW *aView ) // fixme: ugly
{
float size = aView->ToWorld( EDIT_POINT::POINT_SIZE );
unsigned size = std::abs<int>( KiROUND( aView->ToWorld( EDIT_POINT::POINT_SIZE ) ) );
std::deque<EDIT_POINT>::iterator pit, pitEnd;
for( pit = m_points.begin(), pitEnd = m_points.end(); pit != pitEnd; ++pit )
if( m_allowPoints )
{
for( auto& point : m_points )
{
EDIT_POINT& point = *pit;
if( point.WithinPoint( aLocation, size ) )
return &point;
}
}
std::deque<EDIT_LINE>::iterator lit, litEnd;
for( lit = m_lines.begin(), litEnd = m_lines.end(); lit != litEnd; ++lit )
for( auto& line : m_lines )
{
EDIT_LINE& line = *lit;
if( line.WithinPoint( aLocation, size ) )
return &line;
}

View File

@ -219,11 +219,11 @@ public:
///> @copydoc EDIT_POINT::ApplyConstraint()
virtual void ApplyConstraint() override
{
m_origin.ApplyConstraint();
m_end.ApplyConstraint();
if( m_constraint )
m_constraint->Apply();
m_origin.ApplyConstraint();
m_end.ApplyConstraint();
}
/**
@ -492,6 +492,17 @@ public:
return m_lines.size();
}
void SetAllowPoints( bool aAllow = true )
{
m_allowPoints = aAllow;
}
bool GetAllowPoints() const
{
return m_allowPoints;
}
///> @copydoc VIEW_ITEM::ViewBBox()
virtual const BOX2I ViewBBox() const override;
@ -524,6 +535,7 @@ private:
std::deque<EDIT_POINT> m_points; ///< EDIT_POINTs for modifying m_parent
std::deque<EDIT_LINE> m_lines; ///< EDIT_LINEs for modifying m_parent
std::list<int> m_contours; ///< Indices of end contour points
bool m_allowPoints; ///< If false, only allow editing of EDIT_LINES
};
#endif /* EDIT_POINTS_H_ */

View File

@ -200,6 +200,7 @@ public:
{
auto zone = static_cast<const ZONE_CONTAINER*>( aItem );
buildForPolyOutline( points, zone->Outline(), aGal );
points->SetAllowPoints( !zone->GetHV45() );
break;
}
@ -367,7 +368,10 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
//TODO: unify the constraints to solve simultaneously instead of sequentially
m_editedPoint->SetPosition( grid.BestSnapAnchor( evt->Position(),
snapLayers, { item } ) );
bool enableAltConstraint = !!evt->Modifier( MD_CTRL );
// The alternative constraint limits to 45°
bool enableAltConstraint =
( !!evt->Modifier( MD_CTRL ) || !m_editPoints->GetAllowPoints() );
if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint
setAltConstraint( enableAltConstraint );

View File

@ -295,6 +295,22 @@ void ZONE_CREATE_HELPER::OnComplete( const POLYGON_GEOM_MANAGER& aMgr )
outline->Append( finalPoints.CPoint( i ) );
}
// In DEG45 mode, we may have intermediate points in the leader that should be
// included as they are shown in the preview. These typically maintain the
// 45 constraint
if( aMgr.GetLeaderMode() == POLYGON_GEOM_MANAGER::LEADER_MODE::DEG45 )
{
auto pts = aMgr.GetLeaderLinePoints();
if( outline->TotalVertices() > 0 )
outline->RemoveVertex( outline->TotalVertices() - 1 );
// The first 2 points of the leader are the continuation of the previous segment
// The third point is where it intersects with the extension from the 0-th segment
for( int i = 2; i < pts.PointCount(); i++ )
outline->Append( pts.CPoint( i ) );
}
outline->Outline( 0 ).SetClosed( true );
outline->RemoveNullSegments();