diff options
author | saurabhb17 | 2020-02-26 15:57:49 +0530 |
---|---|---|
committer | saurabhb17 | 2020-02-26 15:57:49 +0530 |
commit | aa35045840b78d3f48212db45da59a2e5c69b223 (patch) | |
tree | 6acee185a4dc19113fcbf0f9a3d6941085dedaf7 /pcbnew/tools/grid_helper.cpp | |
parent | 0db48f6533517ecebfd9f0693f89deca28408b76 (diff) | |
download | KiCad-eSim-aa35045840b78d3f48212db45da59a2e5c69b223.tar.gz KiCad-eSim-aa35045840b78d3f48212db45da59a2e5c69b223.tar.bz2 KiCad-eSim-aa35045840b78d3f48212db45da59a2e5c69b223.zip |
Added main execs
Diffstat (limited to 'pcbnew/tools/grid_helper.cpp')
-rw-r--r-- | pcbnew/tools/grid_helper.cpp | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/pcbnew/tools/grid_helper.cpp b/pcbnew/tools/grid_helper.cpp new file mode 100644 index 0000000..4e811ca --- /dev/null +++ b/pcbnew/tools/grid_helper.cpp @@ -0,0 +1,393 @@ +/* + * 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 ) +{ + m_diagonalAuxAxesEnable = true; +} + + +GRID_HELPER::~GRID_HELPER() +{ +} + + +void GRID_HELPER::SetGrid( int aSize ) +{ + assert( false ); +} + + +void GRID_HELPER::SetOrigin( const VECTOR2I& aOrigin ) +{ + assert( false ); +} + + +VECTOR2I GRID_HELPER::GetGrid() const +{ + PCB_SCREEN* screen = m_frame->GetScreen(); + + const wxRealPoint& size = screen->GetGridSize(); + + return VECTOR2I( KiROUND( size.x ), KiROUND( size.y ) ); +} + + +VECTOR2I GRID_HELPER::GetOrigin() const +{ + return VECTOR2I( m_frame->GetGridOrigin() ); +} + + +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 +{ + const VECTOR2D gridOffset( GetOrigin() ); + const VECTOR2D gridSize( GetGrid() ); + + VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / gridSize.x ) * gridSize.x + gridOffset.x, + KiROUND( ( 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::AlignToSegment ( const VECTOR2I& aPoint, const SEG& aSeg ) +{ + OPT_VECTOR2I pts[6]; + + VECTOR2I origin( GetOrigin() ); + VECTOR2I grid( GetGrid() ); + + const VECTOR2D gridOffset( GetOrigin() ); + const VECTOR2D gridSize( GetGrid() ); + + VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / gridSize.x ) * gridSize.x + gridOffset.x, + KiROUND( ( aPoint.y - gridOffset.y ) / gridSize.y ) * gridSize.y + gridOffset.y ); + + pts[0] = aSeg.A; + pts[1] = aSeg.B; + pts[2] = aSeg.IntersectLines( SEG( nearest, nearest + VECTOR2I( 1, 0 ) ) ); + pts[3] = aSeg.IntersectLines( SEG( nearest, nearest + VECTOR2I( 0, 1 ) ) ); + + int min_d = std::numeric_limits<int>::max(); + + for( int i = 0; i < 4; i++ ) + { + if( pts[i] && aSeg.Contains( *pts[i] ) ) + { + int d = (*pts[i] - aPoint).EuclideanNorm(); + + if( d < min_d ) + { + min_d = d; + nearest = *pts[i]; + } + } + } + + 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 ) const +{ + 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_PAD_T: + { + D_PAD* pad = static_cast<D_PAD*>( aItem ); + 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_VIA_T: + addAnchor( aItem->GetPosition(), CORNER | SNAPPABLE, aItem ); + 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( const 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; +} |