diff --git a/common/preview_items/polygon_geom_manager.cpp b/common/preview_items/polygon_geom_manager.cpp index 82276ae3ec..f2ac811e9c 100644 --- a/common/preview_items/polygon_geom_manager.cpp +++ b/common/preview_items/polygon_geom_manager.cpp @@ -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 #include @@ -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::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; + } + } + } + + m_leaderPts = SHAPE_LINE_CHAIN( lastPt, newEnd ); + + if( pt ) + m_leaderPts.Append( *pt ); + } + else + { + // direct segment + m_leaderPts = SHAPE_LINE_CHAIN( lastPt, aEndPoint ); } - // direct segment - m_leaderPts = SHAPE_LINE_CHAIN( lastPt, newEnd ); m_client.OnGeometryChange( *this ); } diff --git a/common/tool/edit_points.cpp b/common/tool/edit_points.cpp index a29cf59f56..01d6ce63f9 100644 --- a/common/tool/edit_points.cpp +++ b/common/tool/edit_points.cpp @@ -37,30 +37,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( KiROUND( aView->ToWorld( EDIT_POINT::POINT_SIZE ) ) ); - std::deque::iterator pit, pitEnd; - for( pit = m_points.begin(), pitEnd = m_points.end(); pit != pitEnd; ++pit ) + if( m_allowPoints ) { - EDIT_POINT& point = *pit; - - if( point.WithinPoint( aLocation, size ) ) - return &point; + for( auto& point : m_points ) + { + if( point.WithinPoint( aLocation, size ) ) + return &point; + } } - std::deque::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; } diff --git a/include/preview_items/polygon_geom_manager.h b/include/preview_items/polygon_geom_manager.h index 101a83181a..a019362182 100644 --- a/include/preview_items/polygon_geom_manager.h +++ b/include/preview_items/polygon_geom_manager.h @@ -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. diff --git a/include/tool/edit_points.h b/include/tool/edit_points.h index 7a4c43d98f..82f068edf2 100644 --- a/include/tool/edit_points.h +++ b/include/tool/edit_points.h @@ -237,11 +237,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(); } /** @@ -510,6 +510,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; @@ -542,6 +553,7 @@ private: std::deque m_points; ///< EDIT_POINTs for modifying m_parent std::deque m_lines; ///< EDIT_LINEs for modifying m_parent std::list m_contours; ///< Indices of end contour points + bool m_allowPoints; ///< If false, only allow editing of EDIT_LINES }; #endif /* EDIT_POINTS_H_ */ diff --git a/pcbnew/tools/point_editor.cpp b/pcbnew/tools/point_editor.cpp index d55330919c..36ba791e27 100644 --- a/pcbnew/tools/point_editor.cpp +++ b/pcbnew/tools/point_editor.cpp @@ -187,6 +187,7 @@ public: { auto zone = static_cast( aItem ); buildForPolyOutline( points, zone->Outline(), aGal ); + points->SetAllowPoints( !zone->GetHV45() ); break; } @@ -353,7 +354,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 ); diff --git a/pcbnew/tools/zone_create_helper.cpp b/pcbnew/tools/zone_create_helper.cpp index 99a6e32608..321858f8f7 100644 --- a/pcbnew/tools/zone_create_helper.cpp +++ b/pcbnew/tools/zone_create_helper.cpp @@ -278,6 +278,22 @@ void ZONE_CREATE_HELPER::OnComplete( const POLYGON_GEOM_MANAGER& aMgr ) for( int i = 0; i < finalPoints.PointCount(); ++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->RemoveNullSegments();