2024-10-25 00:35:50 +02:00
/*
* KiRouter - a push - and - ( sometimes - ) shove PCB router
*
2025-01-01 13:30:11 -08:00
* Copyright The KiCad Developers , see AUTHORS . txt for contributors .
2024-10-25 00:35:50 +02:00
* Author : Tomasz Wlostowski < tomasz . wlostowski @ cern . ch >
*
* This program is free software : you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation , either version 3 of the License , or ( at your
* option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# ifndef __PNS_MULTI_DRAGGER_H
# define __PNS_MULTI_DRAGGER_H
# include <memory>
# include <math/vector2d.h>
# include "pns_node.h"
# include "pns_via.h"
# include "pns_line.h"
# include "pns_drag_algo.h"
# include "pns_itemset.h"
# include "pns_layerset.h"
# include "pns_mouse_trail_tracer.h"
namespace PNS {
class ROUTER ;
class SHOVE ;
class OPTIMIZER ;
/**
* MULTI_DRAGGER
*
* Dragging algorithm for multiple segments . Very trival version for demonstration purposes .
*/
class MULTI_DRAGGER : public DRAG_ALGO
{
public :
MULTI_DRAGGER ( ROUTER * aRouter ) ;
~ MULTI_DRAGGER ( ) ;
/**
* Function Start ( )
*
* Starts routing a single track at point aP , taking item aStartItem as anchor
* ( unless NULL ) . Returns true if a dragging operation has started .
*/
virtual bool Start ( const VECTOR2I & aP , ITEM_SET & aPrimitives ) override ;
/**
* Function Drag ( )
*
* Drags the current segment / corner / via to the point aP .
* @ return true , if dragging finished with success .
*/
bool Drag ( const VECTOR2I & aP ) override ;
/**
* Function FixRoute ( )
*
* Checks if the result of current dragging operation is correct
* and eventually commits it to the world .
* @ return true , if dragging finished with success .
*/
bool FixRoute ( bool aForceCommit ) override ;
/**
* Function CurrentNode ( )
*
* Returns the most recent world state , including all
* items changed due to dragging operation .
*/
NODE * CurrentNode ( ) const override ;
/**
* Function CurrentNets ( )
*
* Returns the net code ( s ) of currently routed track ( s ) .
*/
const std : : vector < NET_HANDLE > CurrentNets ( ) const override ;
/**
* Function CurrentLayer ( )
*
* Returns the layer of currently routed track .
*/
int CurrentLayer ( ) const override ;
/**
* Function Traces ( )
*
* Returns the set of dragged items .
*/
const ITEM_SET Traces ( ) override ;
void SetMode ( PNS : : DRAG_MODE aDragMode ) override ;
PNS : : DRAG_MODE Mode ( ) const override ;
// Use case: we are dragging multiple tracks. The router erases a few of them, adds a few new ones. For the ease of use, it would be good for the tracks the be still selected when
2024-12-30 21:20:14 +00:00
// the drag operation is completed. This method returns a set of the 'leader' (segments/arcs that have been selected for multi-fragging)
2024-10-25 00:35:50 +02:00
virtual std : : vector < PNS : : ITEM * > GetLastCommittedLeaderSegments ( ) override { return m_leaderSegments ; } ;
virtual bool GetForceMarkObstaclesMode ( bool * aDragStatus ) const override
{
* aDragStatus = m_dragStatus ;
return false ;
}
2024-12-30 21:20:14 +00:00
2024-10-25 00:35:50 +02:00
private :
2024-12-30 21:20:14 +00:00
2024-10-25 00:35:50 +02:00
struct MDRAG_LINE
{
2024-11-03 08:52:51 -05:00
ITEM * leaderItem = nullptr ;
2024-10-25 00:35:50 +02:00
std : : vector < PNS : : ITEM * > originalLeaders ;
2024-11-03 08:52:51 -05:00
bool isStrict = false ;
bool isMidSeg = false ;
bool isCorner = false ;
bool isDraggable = false ;
2024-10-25 00:35:50 +02:00
int leaderSegIndex = - 1 ;
2024-12-30 21:20:14 +00:00
bool cornerIsLast = false ;
2024-10-25 00:35:50 +02:00
PNS : : LINE originalLine ; // complete line (in a bundle) to drag
PNS : : LINE preDragLine ; // complete line (in a bundle) to drag
PNS : : LINE draggedLine ; // result of the drag calculation
PNS : : LINE preShoveLine ; // result of the drag calculation
2024-12-30 21:20:14 +00:00
bool dragOK = false ;
bool isPrimaryLine = false ; // when true, it's the "leader"/"primary one" - the one the cursor is attached to
bool clipDone = false ;
int offset = 0 ; // distance between this line and the primary one (only applicable if the respective end segments are parallel)
2024-10-25 00:35:50 +02:00
SEG midSeg ;
// VECTOR2I dragAnchor;
2024-12-30 21:20:14 +00:00
int dragDist = 0 ;
int cornerDistance = 0 ;
int leaderSegDistance = 0 ;
2024-10-25 00:35:50 +02:00
} ;
bool multidragMarkObstacles ( std : : vector < MDRAG_LINE > & aCompletedLines ) ;
bool multidragShove ( std : : vector < MDRAG_LINE > & aCompletedLines ) ;
bool multidragWalkaround ( std : : vector < MDRAG_LINE > & aCompletedLines ) ;
2024-11-01 21:45:53 +01:00
void restoreLeaderSegments ( std : : vector < MDRAG_LINE > & aCompletedLines ) ;
int findNewLeaderSegment ( const MDRAG_LINE & aLine ) const ;
2024-11-02 18:28:09 +01:00
bool tryWalkaround ( NODE * aNode , LINE & aOrig , LINE & aWalk ) ;
2024-10-25 00:35:50 +02:00
int m_mode ;
bool m_dragStatus ;
PNS_MODE m_currentMode ;
DRAG_MODE m_dragMode ;
std : : vector < MDRAG_LINE > m_mdragLines ;
std : : vector < PNS : : ITEM * > m_leaderSegments ;
NODE * m_lastNode ;
NODE * m_preShoveNode ;
ITEM_SET m_origDraggedItems ;
ITEM_SET m_draggedItems ;
VECTOR2I m_dragStartPoint ;
SEG m_guide ;
std : : unique_ptr < SHOVE > m_shove ;
2024-12-30 21:20:14 +00:00
2024-10-25 00:35:50 +02:00
} ;
}
2024-11-02 18:28:09 +01:00
# endif