From 455fae45d864b0c33f7d73b3c69b203cb72e4cbd Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 17 Jan 2024 15:26:21 +0000 Subject: [PATCH] Support point editing of inverted rectangles. Fixes https://gitlab.com/kicad/code/kicad/-/issues/16595 --- common/tool/edit_points.cpp | 8 ++- include/tool/edit_points.h | 18 +++++-- pcbnew/tools/pcb_point_editor.cpp | 83 ++++++++++++++++++++++++------- 3 files changed, 84 insertions(+), 25 deletions(-) diff --git a/common/tool/edit_points.cpp b/common/tool/edit_points.cpp index b190f78250..e62f670a52 100644 --- a/common/tool/edit_points.cpp +++ b/common/tool/edit_points.cpp @@ -41,8 +41,12 @@ 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 ), m_allowPoints( true ) +EDIT_POINTS::EDIT_POINTS( EDA_ITEM* aParent ) : + EDA_ITEM( NOT_USED ), + m_parent( aParent ), + m_swapX( false ), + m_swapY( false ), + m_allowPoints( true ) { } diff --git a/include/tool/edit_points.h b/include/tool/edit_points.h index cf86e86846..b36c4dd5bc 100644 --- a/include/tool/edit_points.h +++ b/include/tool/edit_points.h @@ -524,12 +524,20 @@ public: return wxT( "EDIT_POINTS" ); } + bool SwapX() const { return m_swapX; } + void SetSwapX( bool aSwap ) { m_swapX = aSwap; } + + bool SwapY() const { return m_swapY; } + void SetSwapY( bool aSwap ) { m_swapY = aSwap; } + private: - EDA_ITEM* m_parent; ///< Parent of the EDIT_POINTs. - 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. + EDA_ITEM* m_parent; ///< Parent of the EDIT_POINTs. + bool m_swapX; ///< Parent's X coords are inverted. + bool m_swapY; ///< Parent's Y coords are inverted. + 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/pcb_point_editor.cpp b/pcbnew/tools/pcb_point_editor.cpp index a2a6d7b77f..a02c966f16 100644 --- a/pcbnew/tools/pcb_point_editor.cpp +++ b/pcbnew/tools/pcb_point_editor.cpp @@ -223,10 +223,23 @@ std::shared_ptr PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem ) break; case SHAPE_T::RECTANGLE: - points->AddPoint( shape->GetTopLeft() ); - points->AddPoint( VECTOR2I( shape->GetBotRight().x, shape->GetTopLeft().y ) ); - points->AddPoint( shape->GetBotRight() ); - points->AddPoint( VECTOR2I( shape->GetTopLeft().x, shape->GetBotRight().y ) ); + { + VECTOR2I topLeft = shape->GetTopLeft(); + VECTOR2I botRight = shape->GetBotRight(); + + points->SetSwapX( topLeft.x > botRight.x ); + points->SetSwapY( topLeft.y > botRight.y ); + + if( points->SwapX() ) + std::swap( topLeft.x, botRight.x ); + + if( points->SwapY() ) + std::swap( topLeft.y, botRight.y ); + + points->AddPoint( topLeft ); + points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) ); + points->AddPoint( botRight ); + points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) ); points->AddLine( points->Point( RECT_TOP_LEFT ), points->Point( RECT_TOP_RIGHT ) ); points->Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( points->Line( RECT_TOP ) ) ); @@ -238,6 +251,7 @@ std::shared_ptr PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem ) points->Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_LEFT ) ) ); break; + } case SHAPE_T::ARC: points->AddPoint( shape->GetCenter() ); @@ -1211,6 +1225,27 @@ void PCB_POINT_EDITOR::updateItem( BOARD_COMMIT* aCommit ) case SHAPE_T::RECTANGLE: { + auto setLeft = + [&]( int left ) + { + m_editPoints->SwapX() ? shape->SetRight( left ) : shape->SetLeft( left ); + }; + auto setRight = + [&]( int right ) + { + m_editPoints->SwapX() ? shape->SetLeft( right ) : shape->SetRight( right ); + }; + auto setTop = + [&]( int top ) + { + m_editPoints->SwapY() ? shape->SetBottom( top ) : shape->SetTop( top ); + }; + auto setBottom = + [&]( int bottom ) + { + m_editPoints->SwapY() ? shape->SetTop( bottom ) : shape->SetBottom( bottom ); + }; + VECTOR2I topLeft = m_editPoints->Point( RECT_TOP_LEFT ).GetPosition(); VECTOR2I topRight = m_editPoints->Point( RECT_TOP_RIGHT ).GetPosition(); VECTOR2I botLeft = m_editPoints->Point( RECT_BOT_LEFT ).GetPosition(); @@ -1223,26 +1258,26 @@ void PCB_POINT_EDITOR::updateItem( BOARD_COMMIT* aCommit ) || isModified( m_editPoints->Point( RECT_BOT_RIGHT ) ) || isModified( m_editPoints->Point( RECT_BOT_LEFT ) ) ) { - shape->SetLeft( topLeft.x ); - shape->SetTop( topLeft.y ); - shape->SetRight( botRight.x ); - shape->SetBottom( botRight.y ); + setLeft( topLeft.x ); + setTop( topLeft.y ); + setRight( botRight.x ); + setBottom( botRight.y ); } else if( isModified( m_editPoints->Line( RECT_TOP ) ) ) { - shape->SetTop( topLeft.y ); + setTop( topLeft.y ); } else if( isModified( m_editPoints->Line( RECT_LEFT ) ) ) { - shape->SetLeft( topLeft.x ); + setLeft( topLeft.x ); } else if( isModified( m_editPoints->Line( RECT_BOT ) ) ) { - shape->SetBottom( botRight.y ); + setBottom( botRight.y ); } else if( isModified( m_editPoints->Line( RECT_RIGHT ) ) ) { - shape->SetRight( botRight.x ); + setRight( botRight.x ); } for( unsigned i = 0; i < m_editPoints->LinesSize(); ++i ) @@ -1828,13 +1863,25 @@ void PCB_POINT_EDITOR::updatePoints() break; case SHAPE_T::RECTANGLE: - m_editPoints->Point( RECT_TOP_LEFT ).SetPosition( shape->GetTopLeft() ); - m_editPoints->Point( RECT_TOP_RIGHT ).SetPosition( shape->GetBotRight().x, - shape->GetTopLeft().y ); - m_editPoints->Point( RECT_BOT_RIGHT ).SetPosition( shape->GetBotRight() ); - m_editPoints->Point( RECT_BOT_LEFT ).SetPosition( shape->GetTopLeft().x, - shape->GetBotRight().y ); + { + VECTOR2I topLeft = shape->GetTopLeft(); + VECTOR2I botRight = shape->GetBotRight(); + + m_editPoints->SetSwapX( topLeft.x > botRight.x ); + m_editPoints->SetSwapY( topLeft.y > botRight.y ); + + if( m_editPoints->SwapX() ) + std::swap( topLeft.x, botRight.x ); + + if( m_editPoints->SwapY() ) + std::swap( topLeft.y, botRight.y ); + + m_editPoints->Point( RECT_TOP_LEFT ).SetPosition( topLeft ); + m_editPoints->Point( RECT_TOP_RIGHT ).SetPosition( botRight.x, topLeft.y ); + m_editPoints->Point( RECT_BOT_RIGHT ).SetPosition( botRight ); + m_editPoints->Point( RECT_BOT_LEFT ).SetPosition( topLeft.x, botRight.y ); break; + } case SHAPE_T::ARC: m_editPoints->Point( ARC_CENTER ).SetPosition( shape->GetCenter() );