Browse Source
bulk improvements for selection and edit tools (GAL) disambiguatin heuristics and smarter grid alignment
pull/2/head
bulk improvements for selection and edit tools (GAL) disambiguatin heuristics and smarter grid alignment
pull/2/head
9 changed files with 1042 additions and 121 deletions
-
21pcbnew/tools/common_actions.cpp
-
7pcbnew/tools/common_actions.h
-
223pcbnew/tools/edit_tool.cpp
-
17pcbnew/tools/edit_tool.h
-
334pcbnew/tools/grid_helper.cpp
-
105pcbnew/tools/grid_helper.h
-
401pcbnew/tools/selection_tool.cpp
-
27pcbnew/tools/selection_tool.h
-
28pcbnew/tools/tools_common.cpp
@ -0,0 +1,334 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2014 CERN |
|||
* @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 2 |
|||
* 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, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <boost/foreach.hpp>
|
|||
#include <boost/bind.hpp>
|
|||
|
|||
#include <wxPcbStruct.h>
|
|||
|
|||
#include <class_board.h>
|
|||
#include <class_module.h>
|
|||
#include <class_edge_mod.h>
|
|||
#include <class_zone.h>
|
|||
#include <class_draw_panel_gal.h>
|
|||
|
|||
#include <view/view_controls.h>
|
|||
#include <gal/graphics_abstraction_layer.h>
|
|||
|
|||
#include <geometry/shape_line_chain.h>
|
|||
|
|||
#include "grid_helper.h"
|
|||
|
|||
GRID_HELPER::GRID_HELPER ( PCB_BASE_FRAME *aFrame ) : |
|||
m_frame ( aFrame ) |
|||
{ |
|||
|
|||
} |
|||
|
|||
GRID_HELPER::~GRID_HELPER () |
|||
{ |
|||
|
|||
} |
|||
|
|||
void GRID_HELPER::SetGrid ( int aSize ) |
|||
{ |
|||
assert ( false ); |
|||
} |
|||
|
|||
void GRID_HELPER::SetOrigin ( const VECTOR2I& aOrigin ) |
|||
{ |
|||
} |
|||
|
|||
VECTOR2I GRID_HELPER::GetGrid () |
|||
{ |
|||
PCB_SCREEN *screen = m_frame->GetScreen(); |
|||
|
|||
const wxRealPoint& size = screen->GetGridSize(); |
|||
|
|||
return VECTOR2I ( KiROUND ( size.x ), KiROUND ( size.y ) ); |
|||
} |
|||
|
|||
VECTOR2I GRID_HELPER::GetOrigin () |
|||
{ |
|||
return VECTOR2I ( 0, 0 ); |
|||
} |
|||
|
|||
void GRID_HELPER::SetAuxAxes ( bool aEnable, const VECTOR2I aOrigin, bool aEnableDiagonal) |
|||
{ |
|||
if( aEnable ) |
|||
m_auxAxis = aOrigin; |
|||
else |
|||
m_auxAxis = boost::optional <VECTOR2I> (); |
|||
|
|||
m_diagonalAuxAxesEnable = aEnable; |
|||
} |
|||
|
|||
VECTOR2I GRID_HELPER::Align ( const VECTOR2I& aPoint ) |
|||
{ |
|||
const VECTOR2D gridOffset ( GetOrigin () ); |
|||
const VECTOR2D gridSize ( GetGrid() ); |
|||
|
|||
VECTOR2I nearest ( round( ( aPoint.x - gridOffset.x ) / gridSize.x ) * gridSize.x + gridOffset.x, |
|||
round( ( aPoint.y - gridOffset.y ) / gridSize.y ) * gridSize.y + gridOffset.y ); |
|||
|
|||
if ( !m_auxAxis ) |
|||
return nearest; |
|||
|
|||
if ( std::abs ( m_auxAxis->x - aPoint.x) < std::abs ( nearest.x - aPoint.x ) ) |
|||
nearest.x = m_auxAxis->x; |
|||
|
|||
if ( std::abs ( m_auxAxis->y - aPoint.y) < std::abs ( nearest.y - aPoint.y ) ) |
|||
nearest.y = m_auxAxis->y; |
|||
|
|||
return nearest; |
|||
} |
|||
|
|||
VECTOR2I GRID_HELPER::BestDragOrigin ( const VECTOR2I &aMousePos, BOARD_ITEM *aItem ) |
|||
{ |
|||
clearAnchors(); |
|||
computeAnchors( aItem, aMousePos ); |
|||
|
|||
double worldScale = m_frame->GetGalCanvas()->GetGAL()->GetWorldScale(); |
|||
double lineSnapMinCornerDistance = 50.0 / worldScale; |
|||
|
|||
ANCHOR* nearestOutline = nearestAnchor ( aMousePos, OUTLINE, LSET::AllLayersMask() ); |
|||
ANCHOR* nearestCorner = nearestAnchor ( aMousePos, CORNER, LSET::AllLayersMask() ); |
|||
ANCHOR* nearestOrigin = nearestAnchor ( aMousePos, ORIGIN, LSET::AllLayersMask() ); |
|||
ANCHOR* best = NULL; |
|||
double minDist = std::numeric_limits<double>::max(); |
|||
|
|||
if (nearestOrigin) |
|||
{ |
|||
minDist = nearestOrigin->Distance(aMousePos); |
|||
best = nearestOrigin; |
|||
} |
|||
|
|||
if (nearestCorner) |
|||
{ |
|||
double dist = nearestCorner->Distance(aMousePos); |
|||
if (dist < minDist) |
|||
{ |
|||
minDist = dist; |
|||
best = nearestCorner; |
|||
} |
|||
} |
|||
|
|||
if (nearestOutline) |
|||
{ |
|||
double dist = nearestOutline->Distance(aMousePos); |
|||
if (minDist > lineSnapMinCornerDistance && dist < minDist) |
|||
best = nearestOutline; |
|||
} |
|||
|
|||
return best ? best->pos : aMousePos; |
|||
} |
|||
|
|||
std::set<BOARD_ITEM *> GRID_HELPER::queryVisible ( const BOX2I& aArea ) |
|||
{ |
|||
std::set <BOARD_ITEM *> items; |
|||
|
|||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems; |
|||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR>::iterator it, it_end; |
|||
|
|||
m_frame->GetGalCanvas()->GetView()->Query( aArea, selectedItems ); // Get the list of selected items
|
|||
|
|||
for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it ) |
|||
{ |
|||
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it->first ); |
|||
if( item->ViewIsVisible() ) |
|||
items.insert ( item ); |
|||
} |
|||
|
|||
return items; |
|||
} |
|||
|
|||
VECTOR2I GRID_HELPER::BestSnapAnchor ( const VECTOR2I &aOrigin, BOARD_ITEM *aDraggedItem ) |
|||
{ |
|||
double worldScale = m_frame->GetGalCanvas()->GetGAL()->GetWorldScale(); |
|||
int snapRange = (int) (100.0 / worldScale); |
|||
|
|||
BOX2I bb ( VECTOR2I ( aOrigin.x - snapRange / 2, aOrigin.y - snapRange/2) , VECTOR2I (snapRange, snapRange) ); |
|||
|
|||
clearAnchors(); |
|||
|
|||
BOOST_FOREACH ( BOARD_ITEM *item, queryVisible ( bb ) ) |
|||
{ |
|||
computeAnchors(item, aOrigin); |
|||
} |
|||
|
|||
LSET layers ( aDraggedItem->GetLayer() ); |
|||
ANCHOR *nearest = nearestAnchor ( aOrigin, CORNER | SNAPPABLE, layers ); |
|||
|
|||
VECTOR2I nearestGrid = Align ( aOrigin ); |
|||
double gridDist = (nearestGrid - aOrigin).EuclideanNorm(); |
|||
if (nearest) |
|||
{ |
|||
double snapDist = nearest->Distance ( aOrigin ); |
|||
|
|||
if(nearest && snapDist < gridDist) |
|||
return nearest->pos; |
|||
} |
|||
|
|||
return nearestGrid; |
|||
} |
|||
|
|||
void GRID_HELPER::computeAnchors ( BOARD_ITEM *aItem, const VECTOR2I& aRefPos ) |
|||
{ |
|||
VECTOR2I origin; |
|||
|
|||
|
|||
switch ( aItem->Type() ) |
|||
{ |
|||
case PCB_MODULE_T: |
|||
{ |
|||
MODULE *mod = static_cast <MODULE *> (aItem); |
|||
addAnchor ( mod->GetPosition(), ORIGIN | SNAPPABLE, mod ); |
|||
|
|||
for (D_PAD *pad = mod->Pads(); pad; pad = pad->Next() ) |
|||
addAnchor ( pad->GetPosition(), CORNER | SNAPPABLE, pad ); |
|||
|
|||
break; |
|||
} |
|||
|
|||
case PCB_MODULE_EDGE_T: |
|||
case PCB_LINE_T: |
|||
{ |
|||
DRAWSEGMENT *dseg = static_cast <DRAWSEGMENT*> (aItem); |
|||
VECTOR2I start = dseg->GetStart(); |
|||
VECTOR2I end = dseg->GetEnd(); |
|||
//LAYER_ID layer = dseg->GetLayer();
|
|||
|
|||
|
|||
switch( dseg->GetShape() ) |
|||
{ |
|||
case S_CIRCLE: |
|||
{ |
|||
int r = (start - end).EuclideanNorm(); |
|||
|
|||
addAnchor ( start, ORIGIN | SNAPPABLE, dseg ); |
|||
addAnchor ( start + VECTOR2I ( -r, 0 ) , OUTLINE | SNAPPABLE, dseg ); |
|||
addAnchor ( start + VECTOR2I ( r, 0 ) , OUTLINE | SNAPPABLE, dseg ); |
|||
addAnchor ( start + VECTOR2I ( 0, -r ) , OUTLINE | SNAPPABLE, dseg); |
|||
addAnchor ( start + VECTOR2I ( 0, r ) , OUTLINE | SNAPPABLE, dseg ); |
|||
break; |
|||
} |
|||
|
|||
case S_ARC: |
|||
{ |
|||
origin = dseg->GetCenter(); |
|||
addAnchor ( dseg->GetArcStart(), CORNER | SNAPPABLE, dseg ); |
|||
addAnchor ( dseg->GetArcEnd(), CORNER | SNAPPABLE, dseg ); |
|||
addAnchor ( origin, ORIGIN | SNAPPABLE, dseg ); |
|||
break; |
|||
} |
|||
|
|||
case S_SEGMENT: |
|||
{ |
|||
origin.x = start.x + ( start.x - end.x ) / 2; |
|||
origin.y = start.y + ( start.y - end.y ) / 2; |
|||
addAnchor ( start, CORNER | SNAPPABLE, dseg ); |
|||
addAnchor ( end, CORNER | SNAPPABLE, dseg ); |
|||
addAnchor ( origin, ORIGIN, dseg ); |
|||
break; |
|||
} |
|||
|
|||
default: |
|||
{ |
|||
origin = dseg->GetStart(); |
|||
addAnchor ( origin, ORIGIN | SNAPPABLE, dseg ); |
|||
break; |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
|
|||
case PCB_TRACE_T: |
|||
{ |
|||
TRACK *track = static_cast <TRACK*> (aItem); |
|||
VECTOR2I start = track->GetStart(); |
|||
VECTOR2I end = track->GetEnd(); |
|||
origin.x = start.x + ( start.x - end.x ) / 2; |
|||
origin.y = start.y + ( start.y - end.y ) / 2; |
|||
addAnchor ( start, CORNER | SNAPPABLE, track ); |
|||
addAnchor ( end, CORNER | SNAPPABLE, track ); |
|||
addAnchor ( origin, ORIGIN, track); |
|||
break; |
|||
} |
|||
|
|||
case PCB_ZONE_AREA_T: |
|||
{ |
|||
const CPolyLine* outline = static_cast<const ZONE_CONTAINER*>( aItem )->Outline(); |
|||
int cornersCount = outline->GetCornersCount(); |
|||
|
|||
SHAPE_LINE_CHAIN lc; |
|||
lc.SetClosed ( true ); |
|||
|
|||
for( int i = 0; i < cornersCount; ++i ) |
|||
{ |
|||
const VECTOR2I p ( outline->GetPos( i ) ); |
|||
addAnchor ( p, CORNER, aItem ); |
|||
lc.Append ( p ); |
|||
} |
|||
|
|||
addAnchor( lc.NearestPoint ( aRefPos ), OUTLINE, aItem ); |
|||
|
|||
break; |
|||
} |
|||
|
|||
case PCB_MODULE_TEXT_T: |
|||
case PCB_TEXT_T: |
|||
addAnchor ( aItem->GetPosition(), ORIGIN, aItem ); |
|||
default: |
|||
|
|||
|
|||
break; |
|||
} |
|||
|
|||
} |
|||
|
|||
GRID_HELPER::ANCHOR* GRID_HELPER::nearestAnchor ( VECTOR2I aPos, int aFlags, LSET aMatchLayers ) |
|||
{ |
|||
double minDist = std::numeric_limits<double>::max(); |
|||
ANCHOR *best = NULL; |
|||
|
|||
BOOST_FOREACH( ANCHOR& a, m_anchors ) |
|||
{ |
|||
if ( !aMatchLayers [ a.item->GetLayer() ] ) |
|||
continue; |
|||
|
|||
if ( ( aFlags & a.flags ) != aFlags ) |
|||
continue; |
|||
|
|||
double dist = a.Distance(aPos); |
|||
|
|||
if(dist < minDist) |
|||
{ |
|||
minDist = dist; |
|||
best = &a; |
|||
} |
|||
} |
|||
|
|||
return best; |
|||
|
|||
} |
@ -0,0 +1,105 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2014 CERN |
|||
* @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 2 |
|||
* 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, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
|||
* or you may search the http://www.gnu.org website for the version 2 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef __GRID_HELPER_H |
|||
#define __GRID_HELPER_H |
|||
|
|||
#include <vector> |
|||
|
|||
#include <math/vector2d.h> |
|||
#include <boost/optional.hpp> |
|||
|
|||
#include <layers_id_colors_and_visibility.h> |
|||
|
|||
class PCB_BASE_FRAME; |
|||
|
|||
class GRID_HELPER { |
|||
public: |
|||
|
|||
GRID_HELPER ( PCB_BASE_FRAME *aFrame ); |
|||
~GRID_HELPER (); |
|||
|
|||
void SetGrid ( int aSize ); |
|||
void SetOrigin ( const VECTOR2I& aOrigin ); |
|||
|
|||
VECTOR2I GetGrid (); |
|||
VECTOR2I GetOrigin (); |
|||
|
|||
void SetAuxAxes ( bool aEnable, const VECTOR2I aOrigin = VECTOR2I(0, 0), bool aEnableDiagonal = false ); |
|||
|
|||
VECTOR2I Align ( const VECTOR2I& aPoint ); |
|||
|
|||
VECTOR2I BestDragOrigin ( const VECTOR2I &aMousePos, BOARD_ITEM *aItem ); |
|||
VECTOR2I BestSnapAnchor ( const VECTOR2I &aOrigin, BOARD_ITEM *aDraggedItem ); |
|||
|
|||
private: |
|||
|
|||
enum ANCHOR_FLAGS { |
|||
CORNER = 0x1, |
|||
OUTLINE = 0x2, |
|||
SNAPPABLE = 0x4, |
|||
ORIGIN = 0x8 |
|||
}; |
|||
|
|||
struct ANCHOR |
|||
{ |
|||
ANCHOR ( VECTOR2I aPos, int aFlags = CORNER | SNAPPABLE, BOARD_ITEM *aItem = NULL ): |
|||
pos (aPos), flags (aFlags), item (aItem) {} ; |
|||
|
|||
VECTOR2I pos; |
|||
int flags; |
|||
BOARD_ITEM *item; |
|||
|
|||
double Distance ( const VECTOR2I& aP ) |
|||
{ |
|||
return (aP - pos).EuclideanNorm(); |
|||
} |
|||
|
|||
bool CanSnapItem ( const BOARD_ITEM *aItem ); |
|||
}; |
|||
|
|||
std::vector<ANCHOR> m_anchors; |
|||
|
|||
std::set<BOARD_ITEM *> queryVisible ( const BOX2I& aArea ); |
|||
|
|||
void addAnchor( VECTOR2I aPos, int aFlags = CORNER | SNAPPABLE, BOARD_ITEM *aItem = NULL ) |
|||
{ |
|||
m_anchors.push_back( ANCHOR( aPos, aFlags, aItem ) ); |
|||
} |
|||
|
|||
ANCHOR* nearestAnchor ( VECTOR2I aPos, int aFlags, LSET aMatchLayers ); |
|||
|
|||
void computeAnchors ( BOARD_ITEM *aItem, const VECTOR2I& aRefPos ); |
|||
|
|||
void clearAnchors () |
|||
{ |
|||
m_anchors.clear(); |
|||
} |
|||
|
|||
PCB_BASE_FRAME* m_frame; |
|||
boost::optional<VECTOR2I> m_auxAxis; |
|||
bool m_diagonalAuxAxesEnable; |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,28 @@ |
|||
#include <io_mgr.h>
|
|||
|
|||
#include <tool/tool_manager.h>
|
|||
|
|||
#include <tools/selection_tool.h>
|
|||
#include <tools/edit_tool.h>
|
|||
#include <tools/drawing_tool.h>
|
|||
#include <tools/point_editor.h>
|
|||
#include <tools/pcbnew_control.h>
|
|||
#include <tools/pcb_editor_control.h>
|
|||
#include <tools/placement_tool.h>
|
|||
#include <tools/common_actions.h>
|
|||
|
|||
#include <router/router_tool.h>
|
|||
#include <router/length_tuner_tool.h>
|
|||
|
|||
void registerAllTools ( TOOL_MANAGER *aToolManager ) |
|||
{ |
|||
aToolManager->RegisterTool( new SELECTION_TOOL ); |
|||
aToolManager->RegisterTool( new ROUTER_TOOL ); |
|||
aToolManager->RegisterTool( new LENGTH_TUNER_TOOL ); |
|||
aToolManager->RegisterTool( new EDIT_TOOL ); |
|||
aToolManager->RegisterTool( new DRAWING_TOOL ); |
|||
aToolManager->RegisterTool( new POINT_EDITOR ); |
|||
aToolManager->RegisterTool( new PCBNEW_CONTROL ); |
|||
aToolManager->RegisterTool( new PCB_EDITOR_CONTROL ); |
|||
aToolManager->RegisterTool( new PLACEMENT_TOOL ); |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue