2013-09-18 17:55:16 +00:00
|
|
|
/*
|
|
|
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
|
|
|
*
|
2014-05-14 13:53:54 +00:00
|
|
|
* Copyright (C) 2013-2014 CERN
|
2023-03-02 14:04:37 +00:00
|
|
|
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
2013-09-18 17:55:16 +00:00
|
|
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
2013-09-26 21:53:54 +00:00
|
|
|
*
|
2013-09-18 17:55:16 +00:00
|
|
|
* 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.
|
2013-09-26 21:53:54 +00:00
|
|
|
*
|
2013-09-18 17:55:16 +00:00
|
|
|
* 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.
|
2013-09-26 21:53:54 +00:00
|
|
|
*
|
2013-09-18 17:55:16 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
2014-05-14 13:53:54 +00:00
|
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
2013-09-18 17:55:16 +00:00
|
|
|
*/
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2015-07-02 14:09:43 +00:00
|
|
|
#include <deque>
|
2013-09-18 17:55:16 +00:00
|
|
|
#include <gal/color4d.h>
|
|
|
|
|
2023-09-18 23:52:27 +00:00
|
|
|
#include <gal/graphics_abstraction_layer.h>
|
2014-05-14 13:53:54 +00:00
|
|
|
#include <geometry/shape_rect.h>
|
2020-01-07 17:12:59 +00:00
|
|
|
#include <geometry/shape_simple.h>
|
2013-09-18 17:55:16 +00:00
|
|
|
#include <pcb_painter.h>
|
2021-06-06 12:59:05 +00:00
|
|
|
#include <trigo.h>
|
2013-09-18 17:55:16 +00:00
|
|
|
|
|
|
|
#include "router_preview_item.h"
|
|
|
|
|
2019-05-17 00:13:21 +00:00
|
|
|
#include "pns_arc.h"
|
2013-09-18 17:55:16 +00:00
|
|
|
#include "pns_line.h"
|
|
|
|
#include "pns_segment.h"
|
|
|
|
#include "pns_via.h"
|
|
|
|
|
2013-10-14 14:13:35 +00:00
|
|
|
using namespace KIGFX;
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2021-07-19 23:56:05 +00:00
|
|
|
|
2023-12-08 16:01:27 +00:00
|
|
|
ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, KIGFX::VIEW* aView, int aFlags ) :
|
|
|
|
EDA_ITEM( NOT_USED ),
|
|
|
|
m_view( aView ),
|
|
|
|
m_shape( nullptr ),
|
|
|
|
m_hole( nullptr ),
|
|
|
|
m_flags( aFlags )
|
2013-09-26 21:53:54 +00:00
|
|
|
{
|
2023-04-06 16:59:43 +00:00
|
|
|
BOARD_ITEM* boardItem = aItem ? aItem->BoardItem() : nullptr;
|
2022-08-30 12:52:34 +00:00
|
|
|
|
|
|
|
// A PNS::SOLID for an edge-cut item must have 0 width for collision calculations, but when
|
|
|
|
// highlighting an edge we want to show it with its parent PCB_SHAPE's shape.
|
|
|
|
if( boardItem && boardItem->IsOnLayer( Edge_Cuts ) )
|
|
|
|
{
|
|
|
|
m_shape = boardItem->GetEffectiveShape()->Clone();
|
|
|
|
}
|
|
|
|
else if( aItem )
|
|
|
|
{
|
|
|
|
m_shape = aItem->Shape()->Clone();
|
2014-11-14 19:19:00 +00:00
|
|
|
|
2022-08-30 12:52:34 +00:00
|
|
|
if( aItem->Hole() )
|
|
|
|
m_hole = aItem->Hole()->Shape()->Clone();
|
|
|
|
}
|
2021-01-03 21:14:44 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
m_clearance = -1;
|
2018-08-28 21:57:31 +00:00
|
|
|
m_originLayer = m_layer = LAYER_SELECT_OVERLAY ;
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2021-12-01 19:31:59 +00:00
|
|
|
m_showClearance = false;
|
2017-01-25 09:33:49 +00:00
|
|
|
|
2015-04-20 14:59:25 +00:00
|
|
|
// initialize variables, overwritten by Update( aItem ), if aItem != NULL
|
|
|
|
m_type = PR_SHAPE;
|
2023-12-08 16:01:27 +00:00
|
|
|
m_width = ( aFlags & PNS_SEMI_SOLID ) ? 1 : 0;
|
2023-12-17 13:46:57 +00:00
|
|
|
m_depth = m_originDepth = aView->GetLayerOrder( m_originLayer );
|
2015-04-20 14:59:25 +00:00
|
|
|
|
2013-09-26 21:53:54 +00:00
|
|
|
if( aItem )
|
|
|
|
Update( aItem );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-07 23:44:31 +00:00
|
|
|
ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const SHAPE& aShape, KIGFX::VIEW* aView ) :
|
2023-12-08 16:01:27 +00:00
|
|
|
EDA_ITEM( NOT_USED ),
|
|
|
|
m_flags( 0 )
|
2022-03-07 23:44:31 +00:00
|
|
|
{
|
|
|
|
m_view = aView;
|
|
|
|
|
|
|
|
m_shape = aShape.Clone();
|
|
|
|
m_hole = nullptr;
|
|
|
|
|
|
|
|
m_clearance = -1;
|
2023-12-17 13:46:57 +00:00
|
|
|
m_originLayer = m_layer = LAYER_SELECT_OVERLAY;
|
2022-03-07 23:44:31 +00:00
|
|
|
|
|
|
|
m_showClearance = false;
|
|
|
|
|
|
|
|
// initialize variables, overwritten by Update( aItem ), if aItem != NULL
|
|
|
|
m_type = PR_SHAPE;
|
|
|
|
m_width = 0;
|
2023-12-17 13:46:57 +00:00
|
|
|
m_depth = m_originDepth = aView->GetLayerOrder( m_originLayer );
|
2022-03-07 23:44:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-18 17:55:16 +00:00
|
|
|
ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM()
|
|
|
|
{
|
2015-07-22 08:46:56 +00:00
|
|
|
delete m_shape;
|
2021-11-19 23:25:25 +00:00
|
|
|
delete m_hole;
|
2013-09-18 17:55:16 +00:00
|
|
|
}
|
2013-09-26 21:53:54 +00:00
|
|
|
|
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
void ROUTER_PREVIEW_ITEM::Update( const PNS::ITEM* aItem )
|
2013-09-18 17:55:16 +00:00
|
|
|
{
|
2014-05-14 13:53:54 +00:00
|
|
|
m_originLayer = aItem->Layers().Start();
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2021-11-19 23:25:25 +00:00
|
|
|
if( const PNS::LINE* l = dyn_cast<const PNS::LINE*>( aItem ) )
|
2015-02-18 00:29:54 +00:00
|
|
|
{
|
2015-02-18 16:53:46 +00:00
|
|
|
if( !l->SegmentCount() )
|
2015-02-18 00:29:54 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-11-19 23:25:25 +00:00
|
|
|
else if( const PNS::VIA* v = dyn_cast<const PNS::VIA*>( aItem ) )
|
2021-06-03 20:36:06 +00:00
|
|
|
{
|
|
|
|
if( v->IsVirtual() )
|
|
|
|
return;
|
|
|
|
}
|
2015-02-18 00:29:54 +00:00
|
|
|
|
|
|
|
assert( m_originLayer >= 0 );
|
2015-02-18 16:53:46 +00:00
|
|
|
|
2014-07-07 08:48:47 +00:00
|
|
|
m_layer = m_originLayer;
|
2014-05-14 13:53:54 +00:00
|
|
|
m_color = getLayerColor( m_originLayer );
|
|
|
|
m_color.a = 0.8;
|
2023-12-21 13:31:47 +00:00
|
|
|
m_depth = m_originDepth - ( ( aItem->Layers().Start() + 1 ) * LayerDepthFactor );
|
2020-10-05 19:54:12 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
switch( aItem->Kind() )
|
|
|
|
{
|
2016-08-29 17:31:13 +00:00
|
|
|
case PNS::ITEM::LINE_T:
|
2014-05-16 11:37:31 +00:00
|
|
|
m_type = PR_SHAPE;
|
2019-05-17 00:13:21 +00:00
|
|
|
m_width = static_cast<const PNS::LINE*>( aItem )->Width();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PNS::ITEM::ARC_T:
|
|
|
|
m_type = PR_SHAPE;
|
|
|
|
m_width = static_cast<const PNS::ARC*>( aItem )->Width();
|
2014-05-16 11:37:31 +00:00
|
|
|
break;
|
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
case PNS::ITEM::SEGMENT_T:
|
2014-05-16 11:37:31 +00:00
|
|
|
m_type = PR_SHAPE;
|
2019-05-17 00:13:21 +00:00
|
|
|
m_width = static_cast<const PNS::SEGMENT*>( aItem )->Width();
|
2014-05-16 11:37:31 +00:00
|
|
|
break;
|
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
case PNS::ITEM::VIA_T:
|
2017-03-13 03:19:33 +00:00
|
|
|
m_originLayer = m_layer = LAYER_VIAS;
|
2014-05-16 11:37:31 +00:00
|
|
|
m_type = PR_SHAPE;
|
|
|
|
m_width = 0;
|
|
|
|
m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 );
|
2024-04-13 02:55:43 +00:00
|
|
|
m_depth = m_originDepth - ( static_cast<double>( PCB_LAYER_ID_COUNT ) * LayerDepthFactor );
|
2021-11-19 23:25:25 +00:00
|
|
|
|
|
|
|
delete m_shape;
|
|
|
|
m_shape = nullptr;
|
|
|
|
|
|
|
|
if( aItem->Shape() )
|
|
|
|
m_shape = aItem->Shape()->Clone();
|
|
|
|
|
|
|
|
delete m_hole;
|
|
|
|
m_hole = nullptr;
|
|
|
|
|
|
|
|
if( aItem->Hole() )
|
2022-08-30 12:52:34 +00:00
|
|
|
m_hole = aItem->Hole()->Shape()->Clone();
|
2021-11-19 23:25:25 +00:00
|
|
|
|
2014-05-16 11:37:31 +00:00
|
|
|
break;
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
case PNS::ITEM::SOLID_T:
|
2014-05-16 11:37:31 +00:00
|
|
|
m_type = PR_SHAPE;
|
|
|
|
break;
|
2013-09-26 21:53:54 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-08-29 14:38:11 +00:00
|
|
|
if( aItem->Marker() & PNS::MK_VIOLATION )
|
2023-12-08 16:01:27 +00:00
|
|
|
m_flags |= PNS_COLLISION;
|
|
|
|
|
|
|
|
if( m_flags & PNS_COLLISION )
|
2014-05-16 11:37:31 +00:00
|
|
|
m_color = COLOR4D( 0, 1, 0, 1 );
|
2023-12-02 10:32:45 +00:00
|
|
|
|
2023-12-08 16:01:27 +00:00
|
|
|
if( m_flags & PNS_HOVER_ITEM )
|
2023-12-02 10:32:45 +00:00
|
|
|
m_color = m_color.WithAlpha( 1.0 );
|
2013-09-18 17:55:16 +00:00
|
|
|
}
|
|
|
|
|
2014-05-16 11:37:31 +00:00
|
|
|
|
2013-09-26 21:53:54 +00:00
|
|
|
const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
|
2013-09-18 17:55:16 +00:00
|
|
|
{
|
2013-09-26 21:53:54 +00:00
|
|
|
BOX2I bbox;
|
|
|
|
|
|
|
|
switch( m_type )
|
|
|
|
{
|
2014-05-14 13:53:54 +00:00
|
|
|
case PR_SHAPE:
|
2018-09-12 14:59:01 +00:00
|
|
|
if( m_shape )
|
|
|
|
{
|
|
|
|
bbox = m_shape->BBox();
|
|
|
|
bbox.Inflate( m_width / 2 );
|
|
|
|
}
|
2021-11-19 23:25:25 +00:00
|
|
|
|
|
|
|
if( m_hole )
|
|
|
|
bbox.Merge( m_hole->BBox() );
|
|
|
|
|
2013-09-26 21:53:54 +00:00
|
|
|
return bbox;
|
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
case PR_POINT:
|
2014-05-16 11:37:31 +00:00
|
|
|
bbox = BOX2I ( m_pos - VECTOR2I( 100000, 100000 ), VECTOR2I( 200000, 200000 ) );
|
2013-09-26 21:53:54 +00:00
|
|
|
return bbox;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bbox;
|
2013-09-18 17:55:16 +00:00
|
|
|
}
|
|
|
|
|
2014-05-16 11:37:31 +00:00
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN_BASE* aL, KIGFX::GAL* gal ) const
|
2014-05-14 13:53:54 +00:00
|
|
|
{
|
2023-03-02 14:04:37 +00:00
|
|
|
wxCHECK( aL, /* void */ );
|
|
|
|
|
2020-02-28 22:52:03 +00:00
|
|
|
gal->SetIsFill( false );
|
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
for( int s = 0; s < aL->GetSegmentCount(); s++ )
|
2023-05-26 03:10:00 +00:00
|
|
|
{
|
|
|
|
SEG seg = aL->GetSegment( s );
|
|
|
|
|
|
|
|
if( seg.A == seg.B )
|
|
|
|
{
|
|
|
|
gal->SetIsFill( true );
|
|
|
|
gal->SetIsStroke( false );
|
|
|
|
gal->DrawCircle( seg.A, gal->GetLineWidth() / 2 );
|
|
|
|
gal->SetIsFill( false );
|
|
|
|
gal->SetIsStroke( true );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gal->DrawLine( seg.A, seg.B );
|
|
|
|
}
|
|
|
|
}
|
2014-05-16 11:37:31 +00:00
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
const SHAPE_LINE_CHAIN* lineChain = dynamic_cast<const SHAPE_LINE_CHAIN*>( aL );
|
|
|
|
|
|
|
|
for( size_t s = 0; lineChain && s < lineChain->ArcCount(); s++ )
|
2020-02-28 22:52:03 +00:00
|
|
|
{
|
2020-10-05 13:55:52 +00:00
|
|
|
const SHAPE_ARC& arc = lineChain->CArcs()[s];
|
2022-01-16 16:15:07 +00:00
|
|
|
EDA_ANGLE start_angle = arc.GetStartAngle();
|
|
|
|
EDA_ANGLE angle = arc.GetCentralAngle();
|
2020-02-28 22:52:03 +00:00
|
|
|
|
2023-08-22 13:06:53 +00:00
|
|
|
gal->DrawArc( arc.GetCenter(), arc.GetRadius(), start_angle, angle);
|
2020-02-28 22:52:03 +00:00
|
|
|
}
|
|
|
|
|
2023-03-02 14:04:37 +00:00
|
|
|
if( aL->IsClosed() )
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->DrawLine( aL->GetSegment( -1 ).B, aL->GetSegment( 0 ).A );
|
2014-05-14 13:53:54 +00:00
|
|
|
}
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2014-05-16 11:37:31 +00:00
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
void ROUTER_PREVIEW_ITEM::drawShape( const SHAPE* aShape, KIGFX::GAL* gal ) const
|
2013-09-18 17:55:16 +00:00
|
|
|
{
|
2021-11-27 00:53:28 +00:00
|
|
|
bool holeDrawn = false;
|
2024-05-23 15:25:58 +00:00
|
|
|
bool showClearance = m_showClearance || ( m_flags | PNS_COLLISION ) > 0;
|
2021-11-27 00:53:28 +00:00
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
switch( aShape->Type() )
|
2013-09-26 21:53:54 +00:00
|
|
|
{
|
2020-10-05 13:55:52 +00:00
|
|
|
case SH_POLY_SET_TRIANGLE:
|
|
|
|
{
|
|
|
|
const SHAPE_LINE_CHAIN_BASE* l = (const SHAPE_LINE_CHAIN_BASE*) aShape;
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2024-05-23 15:25:58 +00:00
|
|
|
if( showClearance && m_clearance > 0 )
|
2014-05-14 13:53:54 +00:00
|
|
|
{
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetLineWidth( m_width + 2 * m_clearance );
|
|
|
|
drawLineChain( l, gal );
|
|
|
|
}
|
|
|
|
|
|
|
|
gal->SetLayerDepth( m_depth );
|
|
|
|
gal->SetLineWidth( m_width );
|
|
|
|
gal->SetStrokeColor( m_color );
|
|
|
|
gal->SetFillColor( m_color );
|
|
|
|
drawLineChain( l, gal );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SH_LINE_CHAIN:
|
|
|
|
{
|
|
|
|
const SHAPE_LINE_CHAIN* l = (const SHAPE_LINE_CHAIN*) aShape;
|
2021-12-05 18:41:39 +00:00
|
|
|
const int w = m_width;
|
2020-10-05 13:55:52 +00:00
|
|
|
|
2024-05-23 15:25:58 +00:00
|
|
|
if( showClearance && m_clearance > 0 )
|
2015-10-05 16:28:41 +00:00
|
|
|
{
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetLineWidth( w + 2 * m_clearance );
|
|
|
|
drawLineChain( l, gal );
|
2015-10-05 16:28:41 +00:00
|
|
|
}
|
2014-12-23 13:01:59 +00:00
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetLayerDepth( m_depth );
|
|
|
|
gal->SetLineWidth( w );
|
|
|
|
gal->SetStrokeColor( m_color );
|
|
|
|
gal->SetFillColor( m_color );
|
|
|
|
drawLineChain( l, gal );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SH_SEGMENT:
|
|
|
|
{
|
|
|
|
const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) aShape;
|
|
|
|
const int w = s->GetWidth();
|
|
|
|
|
2021-11-21 21:54:49 +00:00
|
|
|
gal->SetIsStroke( false );
|
|
|
|
|
2024-05-23 15:25:58 +00:00
|
|
|
if( showClearance && m_clearance > 0 )
|
2015-10-05 16:28:41 +00:00
|
|
|
{
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetLineWidth( w + 2 * m_clearance );
|
|
|
|
gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() + 2 * m_clearance );
|
2015-10-05 16:28:41 +00:00
|
|
|
}
|
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetLayerDepth( m_depth );
|
|
|
|
gal->SetLineWidth( w );
|
|
|
|
gal->SetFillColor( m_color );
|
|
|
|
gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SH_CIRCLE:
|
|
|
|
{
|
2021-11-19 23:25:25 +00:00
|
|
|
const SHAPE_CIRCLE* c = static_cast<const SHAPE_CIRCLE*>( aShape );
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetStrokeColor( m_color );
|
|
|
|
|
2024-05-23 15:25:58 +00:00
|
|
|
if( showClearance && m_clearance > 0 )
|
2015-10-05 16:28:41 +00:00
|
|
|
{
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetIsStroke( false );
|
|
|
|
gal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance );
|
2015-10-05 16:28:41 +00:00
|
|
|
}
|
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetLayerDepth( m_depth );
|
2021-11-19 23:25:25 +00:00
|
|
|
|
2021-11-23 12:12:23 +00:00
|
|
|
if( m_hole && dynamic_cast<SHAPE_CIRCLE*>( m_hole ) )
|
2021-11-19 23:25:25 +00:00
|
|
|
{
|
|
|
|
const SHAPE_CIRCLE* h = static_cast<const SHAPE_CIRCLE*>( m_hole );
|
|
|
|
int halfWidth = m_width / 2;
|
|
|
|
|
|
|
|
gal->SetIsStroke( true );
|
|
|
|
gal->SetIsFill( false );
|
|
|
|
gal->SetLineWidth( halfWidth + c->GetRadius() - h->GetRadius() );
|
|
|
|
gal->DrawCircle( c->GetCenter(), ( halfWidth + c->GetRadius() + h->GetRadius() ) / 2 );
|
2021-11-27 00:53:28 +00:00
|
|
|
|
|
|
|
holeDrawn = true;
|
2021-11-19 23:25:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gal->SetIsStroke( m_width ? true : false );
|
|
|
|
gal->SetLineWidth( m_width );
|
|
|
|
gal->SetFillColor( m_color );
|
|
|
|
gal->DrawCircle( c->GetCenter(), c->GetRadius() );
|
|
|
|
}
|
2020-10-05 13:55:52 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SH_RECT:
|
|
|
|
{
|
|
|
|
const SHAPE_RECT* r = (const SHAPE_RECT*) aShape;
|
|
|
|
gal->SetFillColor( m_color );
|
|
|
|
|
2024-05-23 15:25:58 +00:00
|
|
|
if( showClearance && m_clearance > 0 )
|
2015-10-05 16:28:41 +00:00
|
|
|
{
|
2020-10-05 13:55:52 +00:00
|
|
|
VECTOR2I p0( r->GetPosition() ), s( r->GetSize() );
|
|
|
|
gal->SetIsStroke( true );
|
|
|
|
gal->SetLineWidth( 2 * m_clearance );
|
|
|
|
gal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) );
|
|
|
|
gal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) );
|
|
|
|
gal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) );
|
|
|
|
gal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) );
|
2015-07-02 14:09:43 +00:00
|
|
|
}
|
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetLayerDepth( m_depth );
|
2020-10-10 08:03:23 +00:00
|
|
|
gal->SetIsStroke( m_width ? true : false );
|
|
|
|
gal->SetLineWidth( m_width);
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetStrokeColor( m_color );
|
|
|
|
gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-05-03 17:52:42 +00:00
|
|
|
case SH_SIMPLE:
|
2015-10-05 16:28:41 +00:00
|
|
|
{
|
2020-10-05 13:55:52 +00:00
|
|
|
const SHAPE_SIMPLE* c = (const SHAPE_SIMPLE*) aShape;
|
2015-10-05 16:28:41 +00:00
|
|
|
std::deque<VECTOR2D> polygon = std::deque<VECTOR2D>();
|
2020-10-05 13:55:52 +00:00
|
|
|
|
2015-10-05 16:28:41 +00:00
|
|
|
for( int i = 0; i < c->PointCount(); i++ )
|
|
|
|
{
|
|
|
|
polygon.push_back( c->CDPoint( i ) );
|
|
|
|
}
|
2018-06-29 03:26:36 +00:00
|
|
|
|
|
|
|
gal->SetFillColor( m_color );
|
2015-10-05 16:28:41 +00:00
|
|
|
|
2024-05-23 15:25:58 +00:00
|
|
|
if( showClearance && m_clearance > 0 )
|
2015-10-05 16:28:41 +00:00
|
|
|
{
|
2016-12-02 17:58:12 +00:00
|
|
|
gal->SetIsStroke( true );
|
|
|
|
gal->SetLineWidth( 2 * m_clearance );
|
2021-07-19 23:56:05 +00:00
|
|
|
|
2015-10-05 16:28:41 +00:00
|
|
|
// need the implicit last segment to be explicit for DrawPolyline
|
|
|
|
polygon.push_back( c->CDPoint( 0 ) );
|
2016-12-02 17:58:12 +00:00
|
|
|
gal->DrawPolyline( polygon );
|
2015-10-05 16:28:41 +00:00
|
|
|
}
|
2018-06-29 03:26:36 +00:00
|
|
|
|
|
|
|
gal->SetLayerDepth( m_depth );
|
|
|
|
gal->SetIsStroke( m_width ? true : false );
|
|
|
|
gal->SetLineWidth( m_width );
|
|
|
|
gal->SetStrokeColor( m_color );
|
|
|
|
gal->DrawPolygon( polygon );
|
2015-10-05 16:28:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-02-28 22:52:03 +00:00
|
|
|
case SH_ARC:
|
|
|
|
{
|
2020-10-05 13:55:52 +00:00
|
|
|
const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape );
|
|
|
|
const int w = arc->GetWidth();
|
2022-01-16 16:15:07 +00:00
|
|
|
EDA_ANGLE start_angle = arc->GetStartAngle();
|
|
|
|
EDA_ANGLE angle = arc->GetCentralAngle();
|
2020-02-28 22:52:03 +00:00
|
|
|
|
|
|
|
gal->SetIsFill( false );
|
|
|
|
gal->SetIsStroke( true );
|
|
|
|
|
2024-05-23 15:25:58 +00:00
|
|
|
if( showClearance && m_clearance > 0 )
|
2020-02-28 22:52:03 +00:00
|
|
|
{
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetLineWidth( w + 2 * m_clearance );
|
2023-08-22 13:06:53 +00:00
|
|
|
gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, angle );
|
2020-02-28 22:52:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gal->SetLayerDepth( m_depth );
|
|
|
|
gal->SetStrokeColor( m_color );
|
|
|
|
gal->SetFillColor( m_color );
|
2020-10-05 13:55:52 +00:00
|
|
|
gal->SetLineWidth( w );
|
2023-08-22 13:06:53 +00:00
|
|
|
gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, angle );
|
2020-02-28 22:52:03 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-10-05 16:28:41 +00:00
|
|
|
case SH_COMPOUND:
|
2022-02-05 02:06:25 +00:00
|
|
|
wxFAIL_MSG( wxT( "Router preview item: nested compound shapes not supported" ) );
|
2020-10-05 13:55:52 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SH_POLY_SET:
|
2022-02-05 02:06:25 +00:00
|
|
|
wxFAIL_MSG( wxT( "Router preview item: SHAPE_POLY_SET not supported" ) );
|
2020-10-05 13:55:52 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SH_NULL:
|
|
|
|
break;
|
|
|
|
}
|
2021-11-27 00:53:28 +00:00
|
|
|
|
|
|
|
if( m_hole && !holeDrawn )
|
|
|
|
{
|
|
|
|
gal->SetLayerDepth( m_depth );
|
|
|
|
gal->SetIsStroke( true );
|
|
|
|
gal->SetIsFill( false );
|
|
|
|
gal->SetStrokeColor( m_color );
|
|
|
|
gal->SetLineWidth( 1 );
|
|
|
|
|
|
|
|
SHAPE_CIRCLE* circle = dynamic_cast<SHAPE_CIRCLE*>( m_hole );
|
|
|
|
SHAPE_SEGMENT* slot = dynamic_cast<SHAPE_SEGMENT*>( m_hole );
|
|
|
|
|
|
|
|
if( circle )
|
|
|
|
gal->DrawCircle( circle->GetCenter(), circle->GetRadius() );
|
|
|
|
else if( slot )
|
|
|
|
gal->DrawSegment( slot->GetSeg().A, slot->GetSeg().B, slot->GetWidth() );
|
|
|
|
}
|
2020-10-05 13:55:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
|
|
|
|
{
|
|
|
|
GAL* gal = aView->GetGAL();
|
|
|
|
//col.Brighten(0.7);
|
|
|
|
|
|
|
|
if( m_type == PR_SHAPE )
|
|
|
|
{
|
|
|
|
if( !m_shape )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// N.B. The order of draw here is important
|
|
|
|
// Cairo doesn't current support z-ordering, so we need
|
|
|
|
// to draw the clearance first to ensure it is in the background
|
2023-12-17 13:46:57 +00:00
|
|
|
gal->SetLayerDepth( m_originDepth );
|
2021-07-19 23:56:05 +00:00
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
//TODO(snh) Add configuration option for the color/alpha here
|
|
|
|
gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.9 ) );
|
|
|
|
gal->SetFillColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.7 ) );
|
|
|
|
gal->SetIsStroke( m_width ? true : false );
|
|
|
|
gal->SetIsFill( true );
|
|
|
|
|
2023-12-08 16:01:27 +00:00
|
|
|
// Semi-solids (ie: rule areas) which are not in collision are sketched (ie: outline only)
|
|
|
|
if( ( m_flags & PNS_SEMI_SOLID ) > 0 && ( m_flags & PNS_COLLISION ) == 0 )
|
|
|
|
gal->SetIsFill( false );
|
|
|
|
|
2020-10-05 13:55:52 +00:00
|
|
|
if( m_shape->HasIndexableSubshapes() )
|
|
|
|
{
|
2022-07-21 22:01:50 +00:00
|
|
|
std::vector<const SHAPE*> subshapes;
|
2020-10-05 13:55:52 +00:00
|
|
|
m_shape->GetIndexableSubshapes( subshapes );
|
|
|
|
|
2022-07-21 22:01:50 +00:00
|
|
|
for( const SHAPE* shape : subshapes )
|
2020-10-05 13:55:52 +00:00
|
|
|
drawShape( shape, gal );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
drawShape( m_shape, gal );
|
2014-05-14 13:53:54 +00:00
|
|
|
}
|
2013-09-26 21:53:54 +00:00
|
|
|
}
|
2013-09-18 17:55:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-26 21:53:54 +00:00
|
|
|
const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const
|
2013-09-18 17:55:16 +00:00
|
|
|
{
|
2016-12-02 17:58:12 +00:00
|
|
|
auto settings = static_cast<PCB_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() );
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2022-12-29 12:12:27 +00:00
|
|
|
COLOR4D color = settings->GetLayerColor( aLayer );
|
|
|
|
|
2023-12-08 16:01:27 +00:00
|
|
|
if( m_flags & PNS_HEAD_TRACE )
|
2022-12-29 12:12:27 +00:00
|
|
|
return color.Saturate( 1.0 );
|
2023-12-08 16:01:27 +00:00
|
|
|
else if( m_flags & PNS_HOVER_ITEM )
|
2023-12-02 10:32:45 +00:00
|
|
|
return color.Brightened( 0.7 );
|
2022-12-29 12:12:27 +00:00
|
|
|
|
|
|
|
return color;
|
2013-09-18 17:55:16 +00:00
|
|
|
}
|