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., * or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <limits>
#include <preview_items/polygon_geom_manager.h> #include <preview_items/polygon_geom_manager.h>
@ -67,6 +68,7 @@ bool POLYGON_GEOM_MANAGER::AddPoint( const VECTOR2I& aPt )
void POLYGON_GEOM_MANAGER::SetFinished() void POLYGON_GEOM_MANAGER::SetFinished()
{ {
m_client.OnComplete( *this ); m_client.OnComplete( *this );
} }
@ -144,16 +146,44 @@ void POLYGON_GEOM_MANAGER::updateLeaderPoints( const VECTOR2I& aEndPoint, LEADER
{ {
wxCHECK( m_lockedPoints.PointCount() > 0, /*void*/ ); wxCHECK( m_lockedPoints.PointCount() > 0, /*void*/ );
const VECTOR2I& lastPt = m_lockedPoints.CLastPoint(); const VECTOR2I& lastPt = m_lockedPoints.CLastPoint();
auto newEnd = VECTOR2I( aEndPoint );
if( m_leaderMode == LEADER_MODE::DEG45 || aModifier == LEADER_MODE::DEG45 ) if( m_leaderMode == LEADER_MODE::DEG45 || aModifier == LEADER_MODE::DEG45 )
{ {
const VECTOR2I lineVector( aEndPoint - lastPt ); const VECTOR2I lineVector( aEndPoint - lastPt );
// get a restricted 45/H/V line from the last fixed point to the cursor // 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 ); 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 ); m_client.OnGeometryChange( *this );
} }

View File

@ -95,6 +95,11 @@ public:
*/ */
void SetLeaderMode( LEADER_MODE aMode ); void SetLeaderMode( LEADER_MODE aMode );
LEADER_MODE GetLeaderMode() const
{
return m_leaderMode;
}
/** /**
* Enables/disables self-intersecting polygons. * Enables/disables self-intersecting polygons.
* @param aEnabled true if self-intersecting polygons are enabled. * @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 ) : EDIT_POINTS::EDIT_POINTS( EDA_ITEM* aParent )
EDA_ITEM( NOT_USED ), m_parent( aParent ) : EDA_ITEM( NOT_USED ), m_parent( aParent ), m_allowPoints( true )
{ {
} }
EDIT_POINT* EDIT_POINTS::FindPoint( const VECTOR2I& aLocation, KIGFX::VIEW *aView ) // fixme: ugly 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; if( m_allowPoints )
for( pit = m_points.begin(), pitEnd = m_points.end(); pit != pitEnd; ++pit ) {
for( auto& point : m_points )
{ {
EDIT_POINT& point = *pit;
if( point.WithinPoint( aLocation, size ) ) if( point.WithinPoint( aLocation, size ) )
return &point; return &point;
} }
}
std::deque<EDIT_LINE>::iterator lit, litEnd; for( auto& line : m_lines )
for( lit = m_lines.begin(), litEnd = m_lines.end(); lit != litEnd; ++lit )
{ {
EDIT_LINE& line = *lit;
if( line.WithinPoint( aLocation, size ) ) if( line.WithinPoint( aLocation, size ) )
return &line; return &line;
} }

View File

@ -219,11 +219,11 @@ public:
///> @copydoc EDIT_POINT::ApplyConstraint() ///> @copydoc EDIT_POINT::ApplyConstraint()
virtual void ApplyConstraint() override virtual void ApplyConstraint() override
{ {
m_origin.ApplyConstraint();
m_end.ApplyConstraint();
if( m_constraint ) if( m_constraint )
m_constraint->Apply(); m_constraint->Apply();
m_origin.ApplyConstraint();
m_end.ApplyConstraint();
} }
/** /**
@ -492,6 +492,17 @@ public:
return m_lines.size(); return m_lines.size();
} }
void SetAllowPoints( bool aAllow = true )
{
m_allowPoints = aAllow;
}
bool GetAllowPoints() const
{
return m_allowPoints;
}
///> @copydoc VIEW_ITEM::ViewBBox() ///> @copydoc VIEW_ITEM::ViewBBox()
virtual const BOX2I ViewBBox() const override; 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_POINT> m_points; ///< EDIT_POINTs for modifying m_parent
std::deque<EDIT_LINE> m_lines; ///< EDIT_LINEs 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 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_ */ #endif /* EDIT_POINTS_H_ */

View File

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

View File

@ -295,6 +295,22 @@ void ZONE_CREATE_HELPER::OnComplete( const POLYGON_GEOM_MANAGER& aMgr )
outline->Append( finalPoints.CPoint( i ) ); 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->Outline( 0 ).SetClosed( true );
outline->RemoveNullSegments(); outline->RemoveNullSegments();