ADDED: Connectivity for graphic shapes on copper layers
Graphic shapes (excluding text) can now have nets when on copper layers. Shapes behave like tracks in that they will pick up nets from connected pads, and follow track opacity settings.
This commit is contained in:
parent
812143ac69
commit
a77e630901
|
@ -253,8 +253,8 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
|
||||||
{
|
{
|
||||||
if( At( ptr ).is_array() )
|
if( At( ptr ).is_array() )
|
||||||
{
|
{
|
||||||
At( ptr ).push_back( LAYER_PADS );
|
At( ptr ).push_back( LAYER_PADS - GAL_LAYER_ID_START );
|
||||||
At( ptr ).push_back( LAYER_ZONES );
|
At( ptr ).push_back( LAYER_ZONES - GAL_LAYER_ID_START );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
case PCB_ARC_T:
|
case PCB_ARC_T:
|
||||||
case PCB_VIA_T:
|
case PCB_VIA_T:
|
||||||
case PCB_ZONE_T:
|
case PCB_ZONE_T:
|
||||||
|
case PCB_SHAPE_T:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <geometry/geometry_utils.h>
|
#include <geometry/geometry_utils.h>
|
||||||
#include <board_commit.h>
|
#include <board_commit.h>
|
||||||
#include <thread_pool.h>
|
#include <thread_pool.h>
|
||||||
|
#include <pcb_shape.h>
|
||||||
|
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
|
|
||||||
|
@ -59,25 +60,11 @@ bool CN_CONNECTIVITY_ALGO::Remove( BOARD_ITEM* aItem )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCB_PAD_T:
|
case PCB_PAD_T:
|
||||||
m_itemMap[aItem].MarkItemsAsInvalid();
|
|
||||||
m_itemMap.erase( aItem );
|
|
||||||
m_itemList.SetDirty( true );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PCB_TRACE_T:
|
case PCB_TRACE_T:
|
||||||
case PCB_ARC_T:
|
case PCB_ARC_T:
|
||||||
m_itemMap[aItem].MarkItemsAsInvalid();
|
|
||||||
m_itemMap.erase( aItem );
|
|
||||||
m_itemList.SetDirty( true );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PCB_VIA_T:
|
case PCB_VIA_T:
|
||||||
m_itemMap[aItem].MarkItemsAsInvalid();
|
|
||||||
m_itemMap.erase( aItem );
|
|
||||||
m_itemList.SetDirty( true );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PCB_ZONE_T:
|
case PCB_ZONE_T:
|
||||||
|
case PCB_SHAPE_T:
|
||||||
m_itemMap[aItem].MarkItemsAsInvalid();
|
m_itemMap[aItem].MarkItemsAsInvalid();
|
||||||
m_itemMap.erase ( aItem );
|
m_itemMap.erase ( aItem );
|
||||||
m_itemList.SetDirty( true );
|
m_itemList.SetDirty( true );
|
||||||
|
@ -189,6 +176,16 @@ bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem )
|
||||||
add( m_itemList, static_cast<PCB_VIA*>( aItem ) );
|
add( m_itemList, static_cast<PCB_VIA*>( aItem ) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PCB_SHAPE_T:
|
||||||
|
if( alreadyAdded( aItem ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( !IsCopperLayer( aItem->GetLayer() ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
add( m_itemList, static_cast<PCB_SHAPE*>( aItem ) );
|
||||||
|
break;
|
||||||
|
|
||||||
case PCB_ZONE_T:
|
case PCB_ZONE_T:
|
||||||
{
|
{
|
||||||
ZONE* zone = static_cast<ZONE*>( aItem );
|
ZONE* zone = static_cast<ZONE*>( aItem );
|
||||||
|
@ -305,13 +302,15 @@ const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUST
|
||||||
if( aMode == CSM_PROPAGATE )
|
if( aMode == CSM_PROPAGATE )
|
||||||
{
|
{
|
||||||
return SearchClusters( aMode,
|
return SearchClusters( aMode,
|
||||||
{ PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T, PCB_VIA_T, PCB_FOOTPRINT_T },
|
{ PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T, PCB_VIA_T, PCB_FOOTPRINT_T,
|
||||||
|
PCB_SHAPE_T },
|
||||||
-1 );
|
-1 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return SearchClusters( aMode,
|
return SearchClusters( aMode,
|
||||||
{ PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T, PCB_VIA_T, PCB_ZONE_T, PCB_FOOTPRINT_T },
|
{ PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T, PCB_VIA_T, PCB_ZONE_T,
|
||||||
|
PCB_FOOTPRINT_T, PCB_SHAPE_T },
|
||||||
-1 );
|
-1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,6 +453,7 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
|
||||||
size += zitems.size(); // Once for building RTrees
|
size += zitems.size(); // Once for building RTrees
|
||||||
size += zitems.size(); // Once for adding to connectivity
|
size += zitems.size(); // Once for adding to connectivity
|
||||||
size += aBoard->Tracks().size();
|
size += aBoard->Tracks().size();
|
||||||
|
size += aBoard->Drawings().size();
|
||||||
|
|
||||||
for( FOOTPRINT* footprint : aBoard->Footprints() )
|
for( FOOTPRINT* footprint : aBoard->Footprints() )
|
||||||
size += footprint->Pads().size();
|
size += footprint->Pads().size();
|
||||||
|
@ -534,6 +534,17 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for( BOARD_ITEM* drawing : aBoard->Drawings() )
|
||||||
|
{
|
||||||
|
if( PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( drawing ) )
|
||||||
|
{
|
||||||
|
if( shape->IsOnCopperLayer() )
|
||||||
|
Add( shape );
|
||||||
|
}
|
||||||
|
|
||||||
|
report( ++ii );
|
||||||
|
}
|
||||||
|
|
||||||
if( aReporter )
|
if( aReporter )
|
||||||
{
|
{
|
||||||
aReporter->SetCurrentProgress( (double) ii / (double) size );
|
aReporter->SetCurrentProgress( (double) ii / (double) size );
|
||||||
|
@ -553,6 +564,7 @@ void CN_CONNECTIVITY_ALGO::LocalBuild( const std::vector<BOARD_ITEM*>& aItems )
|
||||||
case PCB_VIA_T:
|
case PCB_VIA_T:
|
||||||
case PCB_PAD_T:
|
case PCB_PAD_T:
|
||||||
case PCB_FOOTPRINT_T:
|
case PCB_FOOTPRINT_T:
|
||||||
|
case PCB_SHAPE_T:
|
||||||
Add( item );
|
Add( item );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,10 @@ int CN_ITEM::AnchorCount() const
|
||||||
case PCB_TRACE_T:
|
case PCB_TRACE_T:
|
||||||
case PCB_ARC_T:
|
case PCB_ARC_T:
|
||||||
return 2; // start and end
|
return 2; // start and end
|
||||||
|
|
||||||
|
case PCB_SHAPE_T:
|
||||||
|
return m_anchors.size();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +72,9 @@ const VECTOR2I CN_ITEM::GetAnchor( int n ) const
|
||||||
case PCB_VIA_T:
|
case PCB_VIA_T:
|
||||||
return static_cast<const PCB_VIA*>( m_parent )->GetStart();
|
return static_cast<const PCB_VIA*>( m_parent )->GetStart();
|
||||||
|
|
||||||
|
case PCB_SHAPE_T:
|
||||||
|
return ( n < static_cast<int>( m_anchors.size() ) ) ? m_anchors[n]->Pos() : VECTOR2I();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_FOR( m_parent->GetClass() );
|
UNIMPLEMENTED_FOR( m_parent->GetClass() );
|
||||||
return VECTOR2I();
|
return VECTOR2I();
|
||||||
|
@ -247,6 +254,21 @@ CN_ITEM* CN_LIST::Add( CN_ZONE_LAYER* zitem )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CN_ITEM* CN_LIST::Add( PCB_SHAPE* shape )
|
||||||
|
{
|
||||||
|
CN_ITEM* item = new CN_ITEM( shape, true );
|
||||||
|
m_items.push_back( item );
|
||||||
|
|
||||||
|
for( const VECTOR2I& point : shape->GetConnectionPoints() )
|
||||||
|
item->AddAnchor( point );
|
||||||
|
|
||||||
|
item->SetLayer( shape->GetLayer() );
|
||||||
|
addItemtoTree( item );
|
||||||
|
SetDirty();
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CN_LIST::RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage )
|
void CN_LIST::RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage )
|
||||||
{
|
{
|
||||||
if( !m_hasInvalid )
|
if( !m_hasInvalid )
|
||||||
|
@ -318,7 +340,16 @@ bool CN_ANCHOR::IsDangling() const
|
||||||
return connected_count < minimal_count;
|
return connected_count < minimal_count;
|
||||||
|
|
||||||
if( Parent()->Type() == PCB_TRACE_T || Parent()->Type() == PCB_ARC_T )
|
if( Parent()->Type() == PCB_TRACE_T || Parent()->Type() == PCB_ARC_T )
|
||||||
|
{
|
||||||
accuracy = KiROUND( static_cast<const PCB_TRACK*>( Parent() )->GetWidth() / 2 );
|
accuracy = KiROUND( static_cast<const PCB_TRACK*>( Parent() )->GetWidth() / 2 );
|
||||||
|
}
|
||||||
|
else if( Parent()->Type() == PCB_SHAPE_T )
|
||||||
|
{
|
||||||
|
auto shape = static_cast<const PCB_SHAPE*>( Parent() );
|
||||||
|
|
||||||
|
if( !shape->IsFilled() )
|
||||||
|
accuracy = KiROUND( shape->GetWidth() / 2 );
|
||||||
|
}
|
||||||
|
|
||||||
// Items with multiple anchors have usually items connected to each anchor.
|
// Items with multiple anchors have usually items connected to each anchor.
|
||||||
// We want only the item count of this anchor point
|
// We want only the item count of this anchor point
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <pad.h>
|
#include <pad.h>
|
||||||
#include <footprint.h>
|
#include <footprint.h>
|
||||||
#include <pcb_track.h>
|
#include <pcb_track.h>
|
||||||
|
#include <pcb_shape.h>
|
||||||
#include <zone.h>
|
#include <zone.h>
|
||||||
|
|
||||||
#include <geometry/shape_poly_set.h>
|
#include <geometry/shape_poly_set.h>
|
||||||
|
@ -423,6 +424,7 @@ public:
|
||||||
CN_ITEM* Add( PCB_ARC* track );
|
CN_ITEM* Add( PCB_ARC* track );
|
||||||
CN_ITEM* Add( PCB_VIA* via );
|
CN_ITEM* Add( PCB_VIA* via );
|
||||||
CN_ITEM* Add( CN_ZONE_LAYER* zitem );
|
CN_ITEM* Add( CN_ZONE_LAYER* zitem );
|
||||||
|
CN_ITEM* Add( PCB_SHAPE* shape );
|
||||||
|
|
||||||
const std::vector<CN_ITEM*> Add( ZONE* zone, PCB_LAYER_ID aLayer );
|
const std::vector<CN_ITEM*> Add( ZONE* zone, PCB_LAYER_ID aLayer );
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,33 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES::DIALOG_GRAPHIC_ITEM_PROPERTIES( PCB_BASE_EDIT_FR
|
||||||
m_LayerSelectionCtrl->SetBoardFrame( m_parent );
|
m_LayerSelectionCtrl->SetBoardFrame( m_parent );
|
||||||
m_LayerSelectionCtrl->Resync();
|
m_LayerSelectionCtrl->Resync();
|
||||||
|
|
||||||
|
m_netSelector->SetBoard( aParent->GetBoard() );
|
||||||
|
m_netSelector->SetNetInfo( &aParent->GetBoard()->GetNetInfo() );
|
||||||
|
|
||||||
|
int net = aShape->GetNetCode();
|
||||||
|
|
||||||
|
if( net >= 0 )
|
||||||
|
{
|
||||||
|
m_netSelector->SetSelectedNetcode( net );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_netSelector->SetIndeterminateString( INDETERMINATE_STATE );
|
||||||
|
m_netSelector->SetIndeterminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto showHideNetInfo =
|
||||||
|
[&]()
|
||||||
|
{
|
||||||
|
m_netSelector->Show( aShape->IsOnCopperLayer() );
|
||||||
|
m_netLabel->Show( aShape->IsOnCopperLayer() );
|
||||||
|
};
|
||||||
|
|
||||||
|
showHideNetInfo();
|
||||||
|
m_LayerSelectionCtrl->Bind( wxEVT_COMBOBOX,
|
||||||
|
[&]( wxCommandEvent& aEvt ) { showHideNetInfo() ;} );
|
||||||
|
|
||||||
|
|
||||||
SetInitialFocus( m_startXCtrl );
|
SetInitialFocus( m_startXCtrl );
|
||||||
|
|
||||||
SetupStandardButtons();
|
SetupStandardButtons();
|
||||||
|
@ -199,6 +226,9 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataToWindow()
|
||||||
m_bezierCtrl2Y.Show( false );
|
m_bezierCtrl2Y.Show( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_netSelector->Show( m_item->IsOnCopperLayer() );
|
||||||
|
m_netLabel->Show( m_item->IsOnCopperLayer() );
|
||||||
|
|
||||||
// Change texts according to the segment shape:
|
// Change texts according to the segment shape:
|
||||||
switch( m_item->GetShape() )
|
switch( m_item->GetShape() )
|
||||||
{
|
{
|
||||||
|
@ -381,6 +411,11 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow()
|
||||||
|
|
||||||
m_item->RebuildBezierToSegmentsPointsList( m_item->GetWidth() );
|
m_item->RebuildBezierToSegmentsPointsList( m_item->GetWidth() );
|
||||||
|
|
||||||
|
if( m_item->IsOnCopperLayer() )
|
||||||
|
m_item->SetNetCode( m_netSelector->GetSelectedNetcode() );
|
||||||
|
else
|
||||||
|
m_item->SetNetCode( -1 );
|
||||||
|
|
||||||
commit.Push( _( "Modify drawing properties" ) );
|
commit.Push( _( "Modify drawing properties" ) );
|
||||||
|
|
||||||
// Notify clients which treat locked and unlocked items differently (ie: POINT_EDITOR)
|
// Notify clients which treat locked and unlocked items differently (ie: POINT_EDITOR)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
|
@ -183,7 +183,14 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind
|
||||||
gbSizer2->Add( m_LayerLabel, wxGBPosition( 5, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
gbSizer2->Add( m_LayerLabel, wxGBPosition( 5, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
||||||
|
|
||||||
m_LayerSelectionCtrl = new PCB_LAYER_BOX_SELECTOR( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
|
m_LayerSelectionCtrl = new PCB_LAYER_BOX_SELECTOR( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
|
||||||
gbSizer2->Add( m_LayerSelectionCtrl, wxGBPosition( 5, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
|
gbSizer2->Add( m_LayerSelectionCtrl, wxGBPosition( 5, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
m_netLabel = new wxStaticText( this, wxID_ANY, _("Net:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_netLabel->Wrap( -1 );
|
||||||
|
gbSizer2->Add( m_netLabel, wxGBPosition( 6, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||||
|
|
||||||
|
m_netSelector = new NET_SELECTOR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
gbSizer2->Add( m_netSelector, wxGBPosition( 6, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
gbSizer2->AddGrowableCol( 1 );
|
gbSizer2->AddGrowableCol( 1 );
|
||||||
|
|
|
@ -2654,7 +2654,7 @@
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="colspan">1</property>
|
<property name="colspan">1</property>
|
||||||
<property name="column">1</property>
|
<property name="column">1</property>
|
||||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND</property>
|
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND</property>
|
||||||
<property name="row">5</property>
|
<property name="row">5</property>
|
||||||
<property name="rowspan">1</property>
|
<property name="rowspan">1</property>
|
||||||
<object class="wxBitmapComboBox" expanded="1">
|
<object class="wxBitmapComboBox" expanded="1">
|
||||||
|
@ -2718,6 +2718,135 @@
|
||||||
<property name="window_style"></property>
|
<property name="window_style"></property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="gbsizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="colspan">1</property>
|
||||||
|
<property name="column">0</property>
|
||||||
|
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property>
|
||||||
|
<property name="row">6</property>
|
||||||
|
<property name="rowspan">1</property>
|
||||||
|
<object class="wxStaticText" expanded="1">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="label">Net:</property>
|
||||||
|
<property name="markup">0</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_netLabel</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style"></property>
|
||||||
|
<property name="subclass">; ; forward_declare</property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
<property name="wrap">-1</property>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="gbsizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="colspan">1</property>
|
||||||
|
<property name="column">1</property>
|
||||||
|
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND</property>
|
||||||
|
<property name="row">6</property>
|
||||||
|
<property name="rowspan">1</property>
|
||||||
|
<object class="CustomControl" expanded="1">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="class">NET_SELECTOR</property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="construction"></property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="declaration"></property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="include">#include <widgets/net_selector.h></property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_netSelector</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="settings"></property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="subclass">; ; forward_declare</property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
|
@ -23,6 +23,7 @@ class PCB_LAYER_BOX_SELECTOR;
|
||||||
#include <wx/gbsizer.h>
|
#include <wx/gbsizer.h>
|
||||||
#include <wx/checkbox.h>
|
#include <wx/checkbox.h>
|
||||||
#include <wx/bmpcbox.h>
|
#include <wx/bmpcbox.h>
|
||||||
|
#include <widgets/net_selector.h>
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
|
@ -79,6 +80,8 @@ class DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE : public DIALOG_SHIM
|
||||||
wxBitmapComboBox* m_lineStyleCombo;
|
wxBitmapComboBox* m_lineStyleCombo;
|
||||||
wxStaticText* m_LayerLabel;
|
wxStaticText* m_LayerLabel;
|
||||||
PCB_LAYER_BOX_SELECTOR* m_LayerSelectionCtrl;
|
PCB_LAYER_BOX_SELECTOR* m_LayerSelectionCtrl;
|
||||||
|
wxStaticText* m_netLabel;
|
||||||
|
NET_SELECTOR* m_netSelector;
|
||||||
wxStdDialogButtonSizer* m_StandardButtonsSizer;
|
wxStdDialogButtonSizer* m_StandardButtonsSizer;
|
||||||
wxButton* m_StandardButtonsSizerOK;
|
wxButton* m_StandardButtonsSizerOK;
|
||||||
wxButton* m_StandardButtonsSizerCancel;
|
wxButton* m_StandardButtonsSizerCancel;
|
||||||
|
|
|
@ -84,14 +84,14 @@ public:
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Checks for track/via/hole <-> clearance
|
* Checks for track/via/hole <-> clearance
|
||||||
* @param track Track to text
|
* @param item Track to text
|
||||||
* @param trackShape Primitive track shape
|
* @param itemShape Primitive track shape
|
||||||
* @param layer Which layer to test (in case of vias this can be multiple
|
* @param layer Which layer to test (in case of vias this can be multiple
|
||||||
* @param other item against which to test the track item
|
* @param other item against which to test the track item
|
||||||
* @return false if there is a clearance violation reported, true if there is none
|
* @return false if there is a clearance violation reported, true if there is none
|
||||||
*/
|
*/
|
||||||
bool testTrackAgainstItem( PCB_TRACK* track, SHAPE* trackShape, PCB_LAYER_ID layer,
|
bool testSingleLayerItemAgainstItem( BOARD_CONNECTED_ITEM* item, SHAPE* itemShape,
|
||||||
BOARD_ITEM* other );
|
PCB_LAYER_ID layer, BOARD_ITEM* other );
|
||||||
|
|
||||||
void testTrackClearances();
|
void testTrackClearances();
|
||||||
|
|
||||||
|
@ -196,9 +196,10 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track, SHAPE* trackShape,
|
bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testSingleLayerItemAgainstItem( BOARD_CONNECTED_ITEM* item,
|
||||||
PCB_LAYER_ID layer,
|
SHAPE* itemShape,
|
||||||
BOARD_ITEM* other )
|
PCB_LAYER_ID layer,
|
||||||
|
BOARD_ITEM* other )
|
||||||
{
|
{
|
||||||
bool testClearance = !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE );
|
bool testClearance = !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE );
|
||||||
bool testShorting = !m_drcEngine->IsErrorLimitExceeded( DRCE_SHORTING_ITEMS );
|
bool testShorting = !m_drcEngine->IsErrorLimitExceeded( DRCE_SHORTING_ITEMS );
|
||||||
|
@ -225,22 +226,25 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
||||||
|
|
||||||
if( testClearance || testShorting )
|
if( testClearance || testShorting )
|
||||||
{
|
{
|
||||||
constraint = m_drcEngine->EvalRules( CLEARANCE_CONSTRAINT, track, other, layer );
|
constraint = m_drcEngine->EvalRules( CLEARANCE_CONSTRAINT, item, other, layer );
|
||||||
clearance = constraint.GetValue().Min();
|
clearance = constraint.GetValue().Min();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE && clearance > 0 )
|
if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE && clearance > 0 )
|
||||||
{
|
{
|
||||||
// Special processing for track:track intersections
|
// Special processing for track:track intersections
|
||||||
if( track->Type() == PCB_TRACE_T && other->Type() == PCB_TRACE_T )
|
if( item->Type() == PCB_TRACE_T && other->Type() == PCB_TRACE_T )
|
||||||
{
|
{
|
||||||
|
PCB_TRACK* track = static_cast<PCB_TRACK*>( item );
|
||||||
|
PCB_TRACK* otherTrack = static_cast<PCB_TRACK*>( other );
|
||||||
|
|
||||||
SEG trackSeg( track->GetStart(), track->GetEnd() );
|
SEG trackSeg( track->GetStart(), track->GetEnd() );
|
||||||
SEG otherSeg( track->GetStart(), track->GetEnd() );
|
SEG otherSeg( otherTrack->GetStart(), otherTrack->GetEnd() );
|
||||||
|
|
||||||
if( OPT_VECTOR2I intersection = trackSeg.Intersect( otherSeg ) )
|
if( OPT_VECTOR2I intersection = trackSeg.Intersect( otherSeg ) )
|
||||||
{
|
{
|
||||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TRACKS_CROSSING );
|
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TRACKS_CROSSING );
|
||||||
drcItem->SetItems( track, other );
|
drcItem->SetItems( item, other );
|
||||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||||
|
|
||||||
reportViolation( drcItem, *intersection, layer );
|
reportViolation( drcItem, *intersection, layer );
|
||||||
|
@ -249,9 +253,9 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( trackShape->Collide( otherShape.get(), clearance - m_drcEpsilon, &actual, &pos ) )
|
if( itemShape->Collide( otherShape.get(), clearance - m_drcEpsilon, &actual, &pos ) )
|
||||||
{
|
{
|
||||||
if( m_drcEngine->IsNetTieExclusion( track->GetNetCode(), layer, pos, other ) )
|
if( m_drcEngine->IsNetTieExclusion( item->GetNetCode(), layer, pos, other ) )
|
||||||
{
|
{
|
||||||
// Collision occurred as track was entering a pad marked as a net-tie. We
|
// Collision occurred as track was entering a pad marked as a net-tie. We
|
||||||
// allow these.
|
// allow these.
|
||||||
|
@ -261,12 +265,11 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
||||||
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_SHORTING_ITEMS );
|
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_SHORTING_ITEMS );
|
||||||
wxString msg;
|
wxString msg;
|
||||||
|
|
||||||
msg.Printf( _( "(nets %s and %s)" ),
|
msg.Printf( _( "(nets %s and %s)" ), item->GetNetname(),
|
||||||
track->GetNetname(),
|
|
||||||
static_cast<BOARD_CONNECTED_ITEM*>( other )->GetNetname() );
|
static_cast<BOARD_CONNECTED_ITEM*>( other )->GetNetname() );
|
||||||
|
|
||||||
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + msg );
|
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + msg );
|
||||||
drce->SetItems( track, other );
|
drce->SetItems( item, other );
|
||||||
|
|
||||||
reportViolation( drce, pos, layer );
|
reportViolation( drce, pos, layer );
|
||||||
has_error = true;
|
has_error = true;
|
||||||
|
@ -283,7 +286,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
||||||
actual );
|
actual );
|
||||||
|
|
||||||
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + msg );
|
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + msg );
|
||||||
drce->SetItems( track, other );
|
drce->SetItems( item, other );
|
||||||
drce->SetViolatingRule( constraint.GetParentRule() );
|
drce->SetViolatingRule( constraint.GetParentRule() );
|
||||||
|
|
||||||
reportViolation( drce, pos, layer );
|
reportViolation( drce, pos, layer );
|
||||||
|
@ -295,11 +298,11 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( testHoles && ( track->HasHole() || other->HasHole() ) )
|
if( testHoles && ( item->HasHole() || other->HasHole() ) )
|
||||||
{
|
{
|
||||||
std::array<BOARD_ITEM*, 2> a{ track, other };
|
std::array<BOARD_ITEM*, 2> a{ item, other };
|
||||||
std::array<BOARD_ITEM*, 2> b{ other, track };
|
std::array<BOARD_ITEM*, 2> b{ other, item };
|
||||||
std::array<SHAPE*, 2> a_shape{ trackShape, otherShape.get() };
|
std::array<SHAPE*, 2> a_shape{ itemShape, otherShape.get() };
|
||||||
|
|
||||||
for( size_t ii = 0; ii < 2; ++ii )
|
for( size_t ii = 0; ii < 2; ++ii )
|
||||||
{
|
{
|
||||||
|
@ -637,7 +640,8 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
||||||
|
|
||||||
// If we get an error, mark the pair as having a clearance error already
|
// If we get an error, mark the pair as having a clearance error already
|
||||||
// Only continue if we are reporting all track errors
|
// Only continue if we are reporting all track errors
|
||||||
if( !testTrackAgainstItem( track, trackShape.get(), layer, other ) )
|
if( !testSingleLayerItemAgainstItem( track, trackShape.get(), layer,
|
||||||
|
other ) )
|
||||||
{
|
{
|
||||||
if( it != checkedPairs.end() )
|
if( it != checkedPairs.end() )
|
||||||
it->second.has_error = true;
|
it->second.has_error = true;
|
||||||
|
@ -720,8 +724,8 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* pa
|
||||||
if( BOARD_CONNECTED_ITEM* connectedItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( other ) )
|
if( BOARD_CONNECTED_ITEM* connectedItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( other ) )
|
||||||
otherNet = connectedItem->GetNetCode();
|
otherNet = connectedItem->GetNetCode();
|
||||||
|
|
||||||
// Pads and vias of the same (defined) net get a waiver on clearance and hole tests
|
// Other objects of the same (defined) net get a waiver on clearance and hole tests
|
||||||
if( ( otherPad || otherVia ) && otherNet && otherNet == padNet )
|
if( otherNet && otherNet == padNet )
|
||||||
{
|
{
|
||||||
testClearance = testShorting = false;
|
testClearance = testShorting = false;
|
||||||
testHoles = false;
|
testHoles = false;
|
||||||
|
@ -1003,10 +1007,82 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testGraphicClearances( )
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::unordered_map<PTR_PTR_CACHE_KEY, layers_checked> checkedPairs;
|
||||||
|
|
||||||
|
auto testCopperGraphic =
|
||||||
|
[&]( PCB_SHAPE* aShape )
|
||||||
|
{
|
||||||
|
PCB_LAYER_ID layer = aShape->GetLayer();
|
||||||
|
|
||||||
|
m_board->m_CopperItemRTreeCache->QueryColliding( aShape, layer, layer,
|
||||||
|
// Filter:
|
||||||
|
[&]( BOARD_ITEM* other ) -> bool
|
||||||
|
{
|
||||||
|
auto otherCItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( other );
|
||||||
|
|
||||||
|
if( otherCItem && otherCItem->GetNetCode() == aShape->GetNetCode() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Pads and tracks handled separately
|
||||||
|
if( other->Type() == PCB_PAD_T || other->Type() == PCB_ARC_T ||
|
||||||
|
other->Type() == PCB_TRACE_T || other->Type() == PCB_VIA_T )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOARD_ITEM* a = aShape;
|
||||||
|
BOARD_ITEM* b = other;
|
||||||
|
|
||||||
|
// store canonical order so we don't collide in both directions
|
||||||
|
// (a:b and b:a)
|
||||||
|
if( static_cast<void*>( a ) > static_cast<void*>( b ) )
|
||||||
|
std::swap( a, b );
|
||||||
|
|
||||||
|
auto it = checkedPairs.find( { a, b } );
|
||||||
|
|
||||||
|
if( it != checkedPairs.end() && it->second.layers.test( layer ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
checkedPairs[ { a, b } ].layers.set( layer );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Visitor:
|
||||||
|
[&]( BOARD_ITEM* other ) -> bool
|
||||||
|
{
|
||||||
|
BOARD_ITEM* a = aShape;
|
||||||
|
BOARD_ITEM* b = other;
|
||||||
|
|
||||||
|
// store canonical order so we don't collide in both directions
|
||||||
|
// (a:b and b:a)
|
||||||
|
if( static_cast<void*>( a ) > static_cast<void*>( b ) )
|
||||||
|
std::swap( a, b );
|
||||||
|
|
||||||
|
auto it = checkedPairs.find( { a, b } );
|
||||||
|
|
||||||
|
if( !testSingleLayerItemAgainstItem( aShape,
|
||||||
|
aShape->GetEffectiveShape().get(),
|
||||||
|
layer, other ) )
|
||||||
|
{
|
||||||
|
if( it != checkedPairs.end() )
|
||||||
|
it->second.has_error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !m_drcEngine->IsCancelled();
|
||||||
|
},
|
||||||
|
m_board->m_DRCMaxClearance );
|
||||||
|
};
|
||||||
|
|
||||||
for( BOARD_ITEM* item : m_board->Drawings() )
|
for( BOARD_ITEM* item : m_board->Drawings() )
|
||||||
{
|
{
|
||||||
testGraphicAgainstZone( item );
|
testGraphicAgainstZone( item );
|
||||||
|
|
||||||
|
if( item->Type() == PCB_SHAPE_T && item->IsOnCopperLayer() )
|
||||||
|
testCopperGraphic( static_cast<PCB_SHAPE*>( item ) );
|
||||||
|
|
||||||
if( !reportProgress( ii++, (int) count, progressDelta ) )
|
if( !reportProgress( ii++, (int) count, progressDelta ) )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -357,6 +357,16 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SHAPE_T::SEGMENT:
|
||||||
|
{
|
||||||
|
SHAPE_LINE_CHAIN asPoly;
|
||||||
|
asPoly.Append( shape->GetStart() );
|
||||||
|
asPoly.Append( shape->GetEnd() );
|
||||||
|
|
||||||
|
testShapeLineChain( asPoly, shape->GetWidth(), layer, item, c );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
|
UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <footprint.h>
|
#include <footprint.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <pad.h>
|
#include <pad.h>
|
||||||
|
#include <pcb_shape.h>
|
||||||
#include <pcb_track.h>
|
#include <pcb_track.h>
|
||||||
#include <zone.h>
|
#include <zone.h>
|
||||||
#include <netinfo.h>
|
#include <netinfo.h>
|
||||||
|
@ -226,6 +227,17 @@ void NETINFO_MAPPING::Update()
|
||||||
for( PCB_TRACK* track : m_board->Tracks() )
|
for( PCB_TRACK* track : m_board->Tracks() )
|
||||||
nets.insert( track->GetNetCode() );
|
nets.insert( track->GetNetCode() );
|
||||||
|
|
||||||
|
for( BOARD_ITEM* item : m_board->Drawings() )
|
||||||
|
{
|
||||||
|
if( item->Type() != PCB_SHAPE_T )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
|
||||||
|
|
||||||
|
if( shape->GetNetCode() > 0 )
|
||||||
|
nets.insert( shape->GetNetCode() );
|
||||||
|
}
|
||||||
|
|
||||||
// footprints/pads
|
// footprints/pads
|
||||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -461,6 +461,8 @@ COLOR4D PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) cons
|
||||||
color.a *= m_zoneOpacity;
|
color.a *= m_zoneOpacity;
|
||||||
else if( item->Type() == PCB_BITMAP_T )
|
else if( item->Type() == PCB_BITMAP_T )
|
||||||
color.a *= m_imageOpacity;
|
color.a *= m_imageOpacity;
|
||||||
|
else if( item->Type() == PCB_SHAPE_T && item->IsOnCopperLayer() )
|
||||||
|
color.a *= m_trackOpacity;
|
||||||
|
|
||||||
if( item->GetForcedTransparency() > 0.0 )
|
if( item->GetForcedTransparency() > 0.0 )
|
||||||
color = color.WithAlpha( color.a * ( 1.0 - item->GetForcedTransparency() ) );
|
color = color.WithAlpha( color.a * ( 1.0 - item->GetForcedTransparency() ) );
|
||||||
|
@ -690,78 +692,8 @@ void PCB_PAINTER::draw( const PCB_TRACK* aTrack, int aLayer )
|
||||||
if( aTrack->GetNetCode() <= NETINFO_LIST::UNCONNECTED )
|
if( aTrack->GetNetCode() <= NETINFO_LIST::UNCONNECTED )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// When drawing netnames, clip the track to the viewport
|
SHAPE_SEGMENT trackShape( { aTrack->GetStart(), aTrack->GetEnd() }, aTrack->GetWidth() );
|
||||||
BOX2D viewport;
|
renderNetNameForSegment( trackShape, color, aTrack->GetUnescapedShortNetname() );
|
||||||
VECTOR2D screenSize = m_gal->GetScreenPixelSize();
|
|
||||||
const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
|
|
||||||
|
|
||||||
viewport.SetOrigin( VECTOR2D( matrix * VECTOR2D( 0, 0 ) ) );
|
|
||||||
viewport.SetEnd( VECTOR2D( matrix * screenSize ) );
|
|
||||||
viewport.Normalize();
|
|
||||||
|
|
||||||
BOX2I clipBox( viewport.GetOrigin(), viewport.GetSize() );
|
|
||||||
SEG visibleSeg( start, end );
|
|
||||||
|
|
||||||
ClipLine( &clipBox, visibleSeg.A.x, visibleSeg.A.y, visibleSeg.B.x, visibleSeg.B.y );
|
|
||||||
|
|
||||||
wxString netName = aTrack->GetUnescapedShortNetname();
|
|
||||||
size_t num_char = netName.size();
|
|
||||||
|
|
||||||
// Check if the track is long enough to have a netname displayed
|
|
||||||
int seg_minlength = track_width * num_char;
|
|
||||||
|
|
||||||
if( visibleSeg.Length() < seg_minlength )
|
|
||||||
return;
|
|
||||||
|
|
||||||
double textSize = track_width;
|
|
||||||
double penWidth = textSize / 12.0;
|
|
||||||
EDA_ANGLE textOrientation;
|
|
||||||
int num_names = 1;
|
|
||||||
|
|
||||||
if( end.y == start.y ) // horizontal
|
|
||||||
{
|
|
||||||
textOrientation = ANGLE_HORIZONTAL;
|
|
||||||
num_names = std::max( num_names,
|
|
||||||
static_cast<int>( aTrack->GetLength() / viewport.GetWidth() ) );
|
|
||||||
}
|
|
||||||
else if( end.x == start.x ) // vertical
|
|
||||||
{
|
|
||||||
textOrientation = ANGLE_VERTICAL;
|
|
||||||
num_names = std::max( num_names,
|
|
||||||
static_cast<int>( aTrack->GetLength() / viewport.GetHeight() ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
textOrientation = -EDA_ANGLE( visibleSeg.B - visibleSeg.A );
|
|
||||||
textOrientation.Normalize90();
|
|
||||||
|
|
||||||
double min_size = std::min( viewport.GetWidth(), viewport.GetHeight() );
|
|
||||||
num_names = std::max( num_names,
|
|
||||||
static_cast<int>( aTrack->GetLength() / ( M_SQRT2 * min_size ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_gal->SetIsStroke( true );
|
|
||||||
m_gal->SetIsFill( false );
|
|
||||||
m_gal->SetStrokeColor( color );
|
|
||||||
m_gal->SetLineWidth( penWidth );
|
|
||||||
m_gal->SetFontBold( false );
|
|
||||||
m_gal->SetFontItalic( false );
|
|
||||||
m_gal->SetFontUnderlined( false );
|
|
||||||
m_gal->SetTextMirrored( false );
|
|
||||||
m_gal->SetGlyphSize( VECTOR2D( textSize * 0.55, textSize * 0.55 ) );
|
|
||||||
m_gal->SetHorizontalJustify( GR_TEXT_H_ALIGN_CENTER );
|
|
||||||
m_gal->SetVerticalJustify( GR_TEXT_V_ALIGN_CENTER );
|
|
||||||
|
|
||||||
for( int ii = 0; ii < num_names; ++ii )
|
|
||||||
{
|
|
||||||
VECTOR2I textPosition =
|
|
||||||
VECTOR2D( start ) * static_cast<double>( num_names - ii ) / ( num_names + 1 )
|
|
||||||
+ VECTOR2D( end ) * static_cast<double>( ii + 1 ) / ( num_names + 1 );
|
|
||||||
|
|
||||||
if( clipBox.Contains( textPosition ) )
|
|
||||||
m_gal->BitmapText( netName, textPosition, textOrientation );
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if( IsCopperLayer( aLayer ) || aLayer == LAYER_LOCKED_ITEM_SHADOW )
|
else if( IsCopperLayer( aLayer ) || aLayer == LAYER_LOCKED_ITEM_SHADOW )
|
||||||
|
@ -797,6 +729,85 @@ void PCB_PAINTER::draw( const PCB_TRACK* aTrack, int aLayer )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PCB_PAINTER::renderNetNameForSegment( const SHAPE_SEGMENT& aSeg, const COLOR4D& aColor,
|
||||||
|
const wxString& aNetName ) const
|
||||||
|
{
|
||||||
|
// When drawing netnames, clip the track to the viewport
|
||||||
|
BOX2D viewport;
|
||||||
|
VECTOR2D screenSize = m_gal->GetScreenPixelSize();
|
||||||
|
const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
|
||||||
|
|
||||||
|
viewport.SetOrigin( VECTOR2D( matrix * VECTOR2D( 0, 0 ) ) );
|
||||||
|
viewport.SetEnd( VECTOR2D( matrix * screenSize ) );
|
||||||
|
viewport.Normalize();
|
||||||
|
|
||||||
|
BOX2I clipBox( viewport.GetOrigin(), viewport.GetSize() );
|
||||||
|
SEG visibleSeg( aSeg.GetSeg().A, aSeg.GetSeg().B );
|
||||||
|
|
||||||
|
ClipLine( &clipBox, visibleSeg.A.x, visibleSeg.A.y, visibleSeg.B.x, visibleSeg.B.y );
|
||||||
|
|
||||||
|
size_t num_char = aNetName.size();
|
||||||
|
|
||||||
|
// Check if the track is long enough to have a netname displayed
|
||||||
|
int seg_minlength = aSeg.GetWidth() * num_char;
|
||||||
|
|
||||||
|
if( visibleSeg.Length() < seg_minlength )
|
||||||
|
return;
|
||||||
|
|
||||||
|
double textSize = aSeg.GetWidth();
|
||||||
|
double penWidth = textSize / 12.0;
|
||||||
|
EDA_ANGLE textOrientation;
|
||||||
|
int num_names = 1;
|
||||||
|
|
||||||
|
VECTOR2I start = aSeg.GetSeg().A;
|
||||||
|
VECTOR2I end = aSeg.GetSeg().B;
|
||||||
|
|
||||||
|
if( end.y == start.y ) // horizontal
|
||||||
|
{
|
||||||
|
textOrientation = ANGLE_HORIZONTAL;
|
||||||
|
num_names = std::max( num_names,
|
||||||
|
static_cast<int>( aSeg.GetSeg().Length() / viewport.GetWidth() ) );
|
||||||
|
}
|
||||||
|
else if( end.x == start.x ) // vertical
|
||||||
|
{
|
||||||
|
textOrientation = ANGLE_VERTICAL;
|
||||||
|
num_names = std::max( num_names,
|
||||||
|
static_cast<int>( aSeg.GetSeg().Length() / viewport.GetHeight() ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textOrientation = -EDA_ANGLE( visibleSeg.B - visibleSeg.A );
|
||||||
|
textOrientation.Normalize90();
|
||||||
|
|
||||||
|
double min_size = std::min( viewport.GetWidth(), viewport.GetHeight() );
|
||||||
|
num_names = std::max( num_names,
|
||||||
|
static_cast<int>( aSeg.GetSeg().Length() / ( M_SQRT2 * min_size ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_gal->SetIsStroke( true );
|
||||||
|
m_gal->SetIsFill( false );
|
||||||
|
m_gal->SetStrokeColor( aColor );
|
||||||
|
m_gal->SetLineWidth( penWidth );
|
||||||
|
m_gal->SetFontBold( false );
|
||||||
|
m_gal->SetFontItalic( false );
|
||||||
|
m_gal->SetFontUnderlined( false );
|
||||||
|
m_gal->SetTextMirrored( false );
|
||||||
|
m_gal->SetGlyphSize( VECTOR2D( textSize * 0.55, textSize * 0.55 ) );
|
||||||
|
m_gal->SetHorizontalJustify( GR_TEXT_H_ALIGN_CENTER );
|
||||||
|
m_gal->SetVerticalJustify( GR_TEXT_V_ALIGN_CENTER );
|
||||||
|
|
||||||
|
for( int ii = 0; ii < num_names; ++ii )
|
||||||
|
{
|
||||||
|
VECTOR2I textPosition =
|
||||||
|
VECTOR2D( start ) * static_cast<double>( num_names - ii ) / ( num_names + 1 )
|
||||||
|
+ VECTOR2D( end ) * static_cast<double>( ii + 1 ) / ( num_names + 1 );
|
||||||
|
|
||||||
|
if( clipBox.Contains( textPosition ) )
|
||||||
|
m_gal->BitmapText( aNetName, textPosition, textOrientation );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PCB_PAINTER::draw( const PCB_ARC* aArc, int aLayer )
|
void PCB_PAINTER::draw( const PCB_ARC* aArc, int aLayer )
|
||||||
{
|
{
|
||||||
VECTOR2D center( aArc->GetCenter() );
|
VECTOR2D center( aArc->GetCenter() );
|
||||||
|
@ -1666,11 +1677,36 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
|
||||||
|
|
||||||
void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
|
void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
|
||||||
{
|
{
|
||||||
COLOR4D color = m_pcbSettings.GetColor( aShape, aShape->GetLayer() );
|
COLOR4D color = m_pcbSettings.GetColor( aShape, aLayer );
|
||||||
bool outline_mode = !viewer_settings()->m_ViewersDisplay.m_DisplayGraphicsFill;
|
bool outline_mode = !viewer_settings()->m_ViewersDisplay.m_DisplayGraphicsFill;
|
||||||
int thickness = getLineThickness( aShape->GetWidth() );
|
int thickness = getLineThickness( aShape->GetWidth() );
|
||||||
PLOT_DASH_TYPE lineStyle = aShape->GetStroke().GetPlotStyle();
|
PLOT_DASH_TYPE lineStyle = aShape->GetStroke().GetPlotStyle();
|
||||||
|
|
||||||
|
if( IsNetnameLayer( aLayer ) )
|
||||||
|
{
|
||||||
|
if( !pcbconfig() || pcbconfig()->m_Display.m_NetNames < 2 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( aShape->GetNetCode() <= NETINFO_LIST::UNCONNECTED )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxString netname = aShape->GetUnescapedShortNetname();
|
||||||
|
|
||||||
|
if( netname.IsEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( aShape->GetShape() == SHAPE_T::SEGMENT )
|
||||||
|
{
|
||||||
|
SHAPE_SEGMENT seg( { aShape->GetStart(), aShape->GetEnd() }, aShape->GetWidth() );
|
||||||
|
renderNetNameForSegment( seg, color, netname );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Maybe use some of the pad code?
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
|
if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
|
||||||
{
|
{
|
||||||
color = m_pcbSettings.GetColor( aShape, aLayer );
|
color = m_pcbSettings.GetColor( aShape, aLayer );
|
||||||
|
|
|
@ -217,6 +217,8 @@ protected:
|
||||||
void strokeText( const wxString& aText, const VECTOR2I& aPosition,
|
void strokeText( const wxString& aText, const VECTOR2I& aPosition,
|
||||||
const TEXT_ATTRIBUTES& aAttrs, const KIFONT::METRICS& aFontMetrics );
|
const TEXT_ATTRIBUTES& aAttrs, const KIFONT::METRICS& aFontMetrics );
|
||||||
|
|
||||||
|
void renderNetNameForSegment( const SHAPE_SEGMENT& aSeg, const COLOR4D& aColor, const wxString& aNetName ) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PCB_RENDER_SETTINGS m_pcbSettings;
|
PCB_RENDER_SETTINGS m_pcbSettings;
|
||||||
FRAME_T m_frameType;
|
FRAME_T m_frameType;
|
||||||
|
|
|
@ -36,14 +36,14 @@
|
||||||
#include <pcb_painter.h>
|
#include <pcb_painter.h>
|
||||||
|
|
||||||
PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, KICAD_T aItemType, SHAPE_T aShapeType ) :
|
PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, KICAD_T aItemType, SHAPE_T aShapeType ) :
|
||||||
BOARD_ITEM( aParent, aItemType ),
|
BOARD_CONNECTED_ITEM( aParent, aItemType ),
|
||||||
EDA_SHAPE( aShapeType, pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
|
EDA_SHAPE( aShapeType, pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, SHAPE_T shapetype ) :
|
PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, SHAPE_T shapetype ) :
|
||||||
BOARD_ITEM( aParent, PCB_SHAPE_T ),
|
BOARD_CONNECTED_ITEM( aParent, PCB_SHAPE_T ),
|
||||||
EDA_SHAPE( shapetype, pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
|
EDA_SHAPE( shapetype, pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,58 @@ bool PCB_SHAPE::IsType( const std::vector<KICAD_T>& aScanTypes ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PCB_SHAPE::SetLayer( PCB_LAYER_ID aLayer )
|
||||||
|
{
|
||||||
|
BOARD_ITEM::SetLayer( aLayer );
|
||||||
|
|
||||||
|
if( !IsOnCopperLayer() )
|
||||||
|
SetNetCode( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<VECTOR2I> PCB_SHAPE::GetConnectionPoints() const
|
||||||
|
{
|
||||||
|
std::vector<VECTOR2I> ret;
|
||||||
|
|
||||||
|
// For filled shapes, we may as well use a centroid
|
||||||
|
if( IsFilled() )
|
||||||
|
{
|
||||||
|
ret.emplace_back( GetCenter() );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( m_shape )
|
||||||
|
{
|
||||||
|
case SHAPE_T::ARC:
|
||||||
|
ret.emplace_back( GetArcMid() );
|
||||||
|
KI_FALLTHROUGH;
|
||||||
|
|
||||||
|
case SHAPE_T::SEGMENT:
|
||||||
|
case SHAPE_T::BEZIER:
|
||||||
|
ret.emplace_back( GetStart() );
|
||||||
|
ret.emplace_back( GetEnd() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SHAPE_T::POLY:
|
||||||
|
for( auto iter = GetPolyShape().CIterate(); iter; ++iter )
|
||||||
|
ret.emplace_back( *iter );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SHAPE_T::RECTANGLE:
|
||||||
|
for( const VECTOR2I& pt : GetRectCorners() )
|
||||||
|
ret.emplace_back( pt );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PCB_SHAPE::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings )
|
void PCB_SHAPE::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings )
|
||||||
{
|
{
|
||||||
m_stroke.SetWidth( settings.GetLineThickness( GetLayer() ) );
|
m_stroke.SetWidth( settings.GetLineThickness( GetLayer() ) );
|
||||||
|
@ -329,6 +381,25 @@ double PCB_SHAPE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PCB_SHAPE::ViewGetLayers( int aLayers[], int& aCount ) const
|
||||||
|
{
|
||||||
|
aLayers[0] = GetLayer();
|
||||||
|
|
||||||
|
if( IsOnCopperLayer() )
|
||||||
|
{
|
||||||
|
aLayers[1] = GetNetnameLayer( aLayers[0] );
|
||||||
|
aCount = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( IsLocked() )
|
||||||
|
aLayers[ aCount++ ] = LAYER_LOCKED_ITEM_SHADOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PCB_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
|
void PCB_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
|
||||||
{
|
{
|
||||||
if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
|
if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
|
||||||
|
@ -350,7 +421,15 @@ void PCB_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
|
||||||
|
|
||||||
wxString PCB_SHAPE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
|
wxString PCB_SHAPE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
|
||||||
{
|
{
|
||||||
return wxString::Format( _( "%s on %s" ), GetFriendlyName(), GetLayerName() );
|
if( GetNetCode() > 0 )
|
||||||
|
{
|
||||||
|
return wxString::Format( _( "%s %s on %s" ), GetFriendlyName(), GetNetnameMsg(),
|
||||||
|
GetLayerName() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return wxString::Format( _( "%s on %s" ), GetFriendlyName(), GetLayerName() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -439,9 +518,9 @@ static struct PCB_SHAPE_DESC
|
||||||
{
|
{
|
||||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||||
REGISTER_TYPE( PCB_SHAPE );
|
REGISTER_TYPE( PCB_SHAPE );
|
||||||
propMgr.AddTypeCast( new TYPE_CAST<PCB_SHAPE, BOARD_ITEM> );
|
propMgr.AddTypeCast( new TYPE_CAST<PCB_SHAPE, BOARD_CONNECTED_ITEM> );
|
||||||
propMgr.AddTypeCast( new TYPE_CAST<PCB_SHAPE, EDA_SHAPE> );
|
propMgr.AddTypeCast( new TYPE_CAST<PCB_SHAPE, EDA_SHAPE> );
|
||||||
propMgr.InheritsAfter( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( BOARD_ITEM ) );
|
propMgr.InheritsAfter( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( BOARD_CONNECTED_ITEM ) );
|
||||||
propMgr.InheritsAfter( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ) );
|
propMgr.InheritsAfter( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ) );
|
||||||
|
|
||||||
// Need to initialise enum_map before we can use a Property enum for it
|
// Need to initialise enum_map before we can use a Property enum for it
|
||||||
|
@ -455,10 +534,13 @@ static struct PCB_SHAPE_DESC
|
||||||
layerEnum.Map( *seq, LSET::Name( *seq ) );
|
layerEnum.Map( *seq, LSET::Name( *seq ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
auto layerProperty = new PROPERTY_ENUM<PCB_SHAPE, PCB_LAYER_ID, BOARD_ITEM>(
|
void ( PCB_SHAPE::*shapeLayerSetter )( PCB_LAYER_ID ) = &PCB_SHAPE::SetLayer;
|
||||||
_HKI( "Layer" ), &PCB_SHAPE::SetLayer, &PCB_SHAPE::GetLayer );
|
PCB_LAYER_ID ( PCB_SHAPE::*shapeLayerGetter )() const = &PCB_SHAPE::GetLayer;
|
||||||
|
|
||||||
propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Layer" ), layerProperty );
|
auto layerProperty = new PROPERTY_ENUM<PCB_SHAPE, PCB_LAYER_ID>(
|
||||||
|
_HKI( "Layer" ), shapeLayerSetter, shapeLayerGetter );
|
||||||
|
|
||||||
|
propMgr.ReplaceProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ), layerProperty );
|
||||||
|
|
||||||
// Only polygons have meaningful Position properties.
|
// Only polygons have meaningful Position properties.
|
||||||
// On other shapes, these are duplicates of the Start properties.
|
// On other shapes, these are duplicates of the Start properties.
|
||||||
|
@ -475,5 +557,17 @@ static struct PCB_SHAPE_DESC
|
||||||
_HKI( "Position X" ), isPolygon );
|
_HKI( "Position X" ), isPolygon );
|
||||||
propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( BOARD_ITEM ),
|
propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( BOARD_ITEM ),
|
||||||
_HKI( "Position Y" ), isPolygon );
|
_HKI( "Position Y" ), isPolygon );
|
||||||
|
|
||||||
|
auto isCopper =
|
||||||
|
[]( INSPECTABLE* aItem ) -> bool
|
||||||
|
{
|
||||||
|
if( PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( aItem ) )
|
||||||
|
return shape->IsOnCopperLayer();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( BOARD_CONNECTED_ITEM ),
|
||||||
|
_HKI( "Net" ), isCopper );
|
||||||
}
|
}
|
||||||
} _PCB_SHAPE_DESC;
|
} _PCB_SHAPE_DESC;
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#ifndef PCB_SHAPE_H
|
#ifndef PCB_SHAPE_H
|
||||||
#define PCB_SHAPE_H
|
#define PCB_SHAPE_H
|
||||||
|
|
||||||
#include <board_item.h>
|
#include <board_connected_item.h>
|
||||||
#include <eda_shape.h>
|
#include <eda_shape.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ class FOOTPRINT;
|
||||||
class MSG_PANEL_ITEM;
|
class MSG_PANEL_ITEM;
|
||||||
|
|
||||||
|
|
||||||
class PCB_SHAPE : public BOARD_ITEM, public EDA_SHAPE
|
class PCB_SHAPE : public BOARD_CONNECTED_ITEM, public EDA_SHAPE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PCB_SHAPE( BOARD_ITEM* aParent, KICAD_T aItemType, SHAPE_T aShapeType );
|
PCB_SHAPE( BOARD_ITEM* aParent, KICAD_T aItemType, SHAPE_T aShapeType );
|
||||||
|
@ -61,11 +61,20 @@ public:
|
||||||
|
|
||||||
bool IsType( const std::vector<KICAD_T>& aScanTypes ) const override;
|
bool IsType( const std::vector<KICAD_T>& aScanTypes ) const override;
|
||||||
|
|
||||||
|
void SetLayer( PCB_LAYER_ID aLayer ) override;
|
||||||
|
PCB_LAYER_ID GetLayer() const override { return m_layer; }
|
||||||
|
|
||||||
void SetPosition( const VECTOR2I& aPos ) override { setPosition( aPos ); }
|
void SetPosition( const VECTOR2I& aPos ) override { setPosition( aPos ); }
|
||||||
VECTOR2I GetPosition() const override { return getPosition(); }
|
VECTOR2I GetPosition() const override { return getPosition(); }
|
||||||
|
|
||||||
VECTOR2I GetCenter() const override { return getCenter(); }
|
VECTOR2I GetCenter() const override { return getCenter(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a list of connection points (may be empty): points where this shape can form
|
||||||
|
* electrical connections to other shapes that are natural "start/end" points.
|
||||||
|
*/
|
||||||
|
std::vector<VECTOR2I> GetConnectionPoints() const;
|
||||||
|
|
||||||
bool HasLineStroke() const override { return true; }
|
bool HasLineStroke() const override { return true; }
|
||||||
|
|
||||||
STROKE_PARAMS GetStroke() const override { return m_stroke; }
|
STROKE_PARAMS GetStroke() const override { return m_stroke; }
|
||||||
|
@ -139,6 +148,8 @@ public:
|
||||||
|
|
||||||
virtual const BOX2I ViewBBox() const override;
|
virtual const BOX2I ViewBBox() const override;
|
||||||
|
|
||||||
|
virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
|
||||||
|
|
||||||
///< @copydoc VIEW_ITEM::ViewGetLOD
|
///< @copydoc VIEW_ITEM::ViewGetLOD
|
||||||
double ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
|
double ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
|
||||||
|
|
||||||
|
|
|
@ -714,6 +714,13 @@ void BRDITEMS_PLOTTER::PlotShape( const PCB_SHAPE* aShape )
|
||||||
gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_ETCHEDCMP );
|
gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_ETCHEDCMP );
|
||||||
gbr_metadata.SetCopper( true );
|
gbr_metadata.SetCopper( true );
|
||||||
}
|
}
|
||||||
|
else if( aShape->GetNetCode() > 0 )
|
||||||
|
{
|
||||||
|
gbr_metadata.SetCopper( true );
|
||||||
|
gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR );
|
||||||
|
gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_NET );
|
||||||
|
gbr_metadata.SetNetName( aShape->GetNetname() );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Graphic items (PCB_SHAPE, TEXT) having no net have the NonConductor attribute
|
// Graphic items (PCB_SHAPE, TEXT) having no net have the NonConductor attribute
|
||||||
|
|
|
@ -2851,8 +2851,17 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE( BOARD_ITEM* aParent )
|
||||||
NeedRIGHT();
|
NeedRIGHT();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_net:
|
||||||
|
if( !shape->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
|
||||||
|
{
|
||||||
|
wxLogError( _( "Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
|
||||||
|
CurSource(), CurLineNumber(), CurOffset() );
|
||||||
|
}
|
||||||
|
NeedRIGHT();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Expecting( "layer, width, fill, tstamp, locked or status" );
|
Expecting( "layer, width, fill, tstamp, locked, net or status" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -986,6 +986,9 @@ void PCB_PLUGIN::format( const PCB_SHAPE* aShape, int aNestLevel ) const
|
||||||
|
|
||||||
formatLayer( aShape->GetLayer() );
|
formatLayer( aShape->GetLayer() );
|
||||||
|
|
||||||
|
if( aShape->GetNetCode() > 0 )
|
||||||
|
m_out->Print( 0, " (net %d)", m_mapping->Translate( aShape->GetNetCode() ) );
|
||||||
|
|
||||||
m_out->Print( 0, " (tstamp %s)", TO_UTF8( aShape->m_Uuid.AsString() ) );
|
m_out->Print( 0, " (tstamp %s)", TO_UTF8( aShape->m_Uuid.AsString() ) );
|
||||||
|
|
||||||
m_out->Print( 0, ")\n" );
|
m_out->Print( 0, ")\n" );
|
||||||
|
|
|
@ -131,7 +131,8 @@ class PCB_PLUGIN; // forward decl
|
||||||
//#define SEXPR_BOARD_FILE_VERSION 20221018 // Via & pad zone-layer-connections
|
//#define SEXPR_BOARD_FILE_VERSION 20221018 // Via & pad zone-layer-connections
|
||||||
//#define SEXPR_BOARD_FILE_VERSION 20230410 // DNP attribute propagated from schematic to attr
|
//#define SEXPR_BOARD_FILE_VERSION 20230410 // DNP attribute propagated from schematic to attr
|
||||||
//#define SEXPR_BOARD_FILE_VERSION 20230517 // Teardrop parameters for pads and vias
|
//#define SEXPR_BOARD_FILE_VERSION 20230517 // Teardrop parameters for pads and vias
|
||||||
#define SEXPR_BOARD_FILE_VERSION 20230620 // PCB Fields
|
//#define SEXPR_BOARD_FILE_VERSION 20230620 // PCB Fields
|
||||||
|
#define SEXPR_BOARD_FILE_VERSION 20230730 // Connectivity for graphic shapes
|
||||||
|
|
||||||
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
|
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
|
||||||
#define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting
|
#define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting
|
||||||
|
|
|
@ -1363,15 +1363,14 @@ bool PNS_KICAD_IFACE_BASE::syncGraphicalItem( PNS::NODE* aWorld, PCB_SHAPE* aIte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
solid->SetNet( -1 );
|
solid->SetAnchorPoints( aItem->GetConnectionPoints() );
|
||||||
|
solid->SetNet( aItem->GetNetCode() );
|
||||||
solid->SetParent( aItem );
|
solid->SetParent( aItem );
|
||||||
solid->SetShape( shape ); // takes ownership
|
solid->SetShape( shape ); // takes ownership
|
||||||
|
|
||||||
if( shapes.size() > 1 )
|
if( shapes.size() > 1 )
|
||||||
solid->SetIsCompoundShapePrimitive();
|
solid->SetIsCompoundShapePrimitive();
|
||||||
|
|
||||||
solid->SetRoutable( false );
|
|
||||||
|
|
||||||
aWorld->Add( std::move( solid ) );
|
aWorld->Add( std::move( solid ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -292,9 +292,6 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
|
||||||
failureReason = _( "Cannot start routing from a text item." );
|
failureReason = _( "Cannot start routing from a text item." );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCB_SHAPE_T:
|
|
||||||
failureReason = _( "Cannot start routing from a graphic." );
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,4 +92,15 @@ void SOLID::SetPos( const VECTOR2I& aCenter )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VECTOR2I SOLID::Anchor( int aN ) const
|
||||||
|
{
|
||||||
|
return m_anchorPoints.empty() ? m_pos : m_anchorPoints[aN];
|
||||||
|
}
|
||||||
|
|
||||||
|
int SOLID::AnchorCount() const
|
||||||
|
{
|
||||||
|
return m_anchorPoints.empty() ? 1 : m_anchorPoints.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
m_pos = aSolid.m_pos;
|
m_pos = aSolid.m_pos;
|
||||||
m_padToDie = aSolid.m_padToDie;
|
m_padToDie = aSolid.m_padToDie;
|
||||||
m_orientation = aSolid.m_orientation;
|
m_orientation = aSolid.m_orientation;
|
||||||
|
m_anchorPoints = aSolid.m_anchorPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
SOLID& operator=( const SOLID& aB )
|
SOLID& operator=( const SOLID& aB )
|
||||||
|
@ -77,6 +78,7 @@ public:
|
||||||
m_pos = aB.m_pos;
|
m_pos = aB.m_pos;
|
||||||
m_padToDie = aB.m_padToDie;
|
m_padToDie = aB.m_padToDie;
|
||||||
m_orientation = aB.m_orientation;
|
m_orientation = aB.m_orientation;
|
||||||
|
m_anchorPoints = aB.m_anchorPoints;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,15 +107,12 @@ public:
|
||||||
int GetPadToDie() const { return m_padToDie; }
|
int GetPadToDie() const { return m_padToDie; }
|
||||||
void SetPadToDie( int aLen ) { m_padToDie = aLen; }
|
void SetPadToDie( int aLen ) { m_padToDie = aLen; }
|
||||||
|
|
||||||
virtual VECTOR2I Anchor( int aN ) const override
|
virtual VECTOR2I Anchor( int aN ) const override;
|
||||||
{
|
|
||||||
return m_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int AnchorCount() const override
|
virtual int AnchorCount() const override;
|
||||||
{
|
|
||||||
return 1;
|
const std::vector<VECTOR2I>& AnchorPoints() const { return m_anchorPoints; }
|
||||||
}
|
void SetAnchorPoints( const std::vector<VECTOR2I>& aPoints ) { m_anchorPoints = aPoints; }
|
||||||
|
|
||||||
VECTOR2I Offset() const { return m_offset; }
|
VECTOR2I Offset() const { return m_offset; }
|
||||||
void SetOffset( const VECTOR2I& aOffset ) { m_offset = aOffset; }
|
void SetOffset( const VECTOR2I& aOffset ) { m_offset = aOffset; }
|
||||||
|
@ -143,6 +142,7 @@ private:
|
||||||
int m_padToDie;
|
int m_padToDie;
|
||||||
EDA_ANGLE m_orientation;
|
EDA_ANGLE m_orientation;
|
||||||
HOLE* m_hole;
|
HOLE* m_hole;
|
||||||
|
std::vector<VECTOR2I> m_anchorPoints;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -423,7 +423,28 @@ const VECTOR2I TOOL_BASE::snapToItem( ITEM* aItem, const VECTOR2I& aP )
|
||||||
switch( aItem->Kind() )
|
switch( aItem->Kind() )
|
||||||
{
|
{
|
||||||
case ITEM::SOLID_T:
|
case ITEM::SOLID_T:
|
||||||
return static_cast<SOLID*>( aItem )->Pos();
|
{
|
||||||
|
SOLID* solid = static_cast<SOLID*>( aItem );
|
||||||
|
|
||||||
|
if( solid->AnchorPoints().empty() )
|
||||||
|
return solid->Anchor( 0 );
|
||||||
|
|
||||||
|
VECTOR2I anchor;
|
||||||
|
SEG::ecoord minDist = std::numeric_limits<SEG::ecoord>::max();
|
||||||
|
|
||||||
|
for( VECTOR2I anchorCandidate : solid->AnchorPoints() )
|
||||||
|
{
|
||||||
|
SEG::ecoord distSq = ( aP - anchorCandidate ).SquaredEuclideanNorm();
|
||||||
|
|
||||||
|
if( distSq < minDist )
|
||||||
|
{
|
||||||
|
minDist = distSq;
|
||||||
|
anchor = anchorCandidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return anchor;
|
||||||
|
}
|
||||||
|
|
||||||
case ITEM::VIA_T:
|
case ITEM::VIA_T:
|
||||||
return static_cast<VIA*>( aItem )->Pos();
|
return static_cast<VIA*>( aItem )->Pos();
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <tools/board_inspection_tool.h>
|
#include <tools/board_inspection_tool.h>
|
||||||
#include <fp_lib_table.h>
|
#include <fp_lib_table.h>
|
||||||
|
#include <pcb_shape.h>
|
||||||
#include <pcbnew_settings.h>
|
#include <pcbnew_settings.h>
|
||||||
#include <widgets/appearance_controls.h>
|
#include <widgets/appearance_controls.h>
|
||||||
#include <widgets/wx_html_report_box.h>
|
#include <widgets/wx_html_report_box.h>
|
||||||
|
@ -84,17 +85,45 @@ bool BOARD_INSPECTION_TOOL::Init()
|
||||||
std::shared_ptr<NET_CONTEXT_MENU> netSubMenu = std::make_shared<NET_CONTEXT_MENU>();
|
std::shared_ptr<NET_CONTEXT_MENU> netSubMenu = std::make_shared<NET_CONTEXT_MENU>();
|
||||||
netSubMenu->SetTool( this );
|
netSubMenu->SetTool( this );
|
||||||
|
|
||||||
static std::vector<KICAD_T> connectedTypes = { PCB_TRACE_T,
|
// Only show the net menu if all items in the selection are connectable
|
||||||
PCB_VIA_T,
|
auto showNetMenuFunc =
|
||||||
PCB_ARC_T,
|
[]( const SELECTION& aSelection )
|
||||||
PCB_PAD_T,
|
{
|
||||||
PCB_ZONE_T };
|
if( aSelection.Empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for( const EDA_ITEM* item : aSelection )
|
||||||
|
{
|
||||||
|
switch( item->Type() )
|
||||||
|
{
|
||||||
|
case PCB_TRACE_T:
|
||||||
|
case PCB_ARC_T:
|
||||||
|
case PCB_VIA_T:
|
||||||
|
case PCB_PAD_T:
|
||||||
|
case PCB_ZONE_T:
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case PCB_SHAPE_T:
|
||||||
|
{
|
||||||
|
if( !static_cast<const PCB_SHAPE*>( item )->IsOnCopperLayer() )
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
CONDITIONAL_MENU& menu = selectionTool->GetToolMenu().GetMenu();
|
CONDITIONAL_MENU& menu = selectionTool->GetToolMenu().GetMenu();
|
||||||
|
|
||||||
selectionTool->GetToolMenu().RegisterSubMenu( netSubMenu );
|
selectionTool->GetToolMenu().RegisterSubMenu( netSubMenu );
|
||||||
|
|
||||||
menu.AddMenu( netSubMenu.get(), SELECTION_CONDITIONS::OnlyTypes( connectedTypes ), 100 );
|
menu.AddMenu( netSubMenu.get(), showNetMenuFunc, 100 );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1616,7 +1645,7 @@ int BOARD_INSPECTION_TOOL::HighlightItem( const TOOL_EVENT& aEvent )
|
||||||
guide.SetPreferredLayer( activeLayer );
|
guide.SetPreferredLayer( activeLayer );
|
||||||
|
|
||||||
GENERAL_COLLECTOR collector;
|
GENERAL_COLLECTOR collector;
|
||||||
collector.Collect( board, { PCB_PAD_T, PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T }, aPosition,
|
collector.Collect( board, { PCB_PAD_T, PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T, PCB_SHAPE_T }, aPosition,
|
||||||
guide );
|
guide );
|
||||||
|
|
||||||
if( collector.GetCount() == 0 )
|
if( collector.GetCount() == 0 )
|
||||||
|
@ -1935,7 +1964,8 @@ void BOARD_INSPECTION_TOOL::calculateSelectionRatsnest( const VECTOR2I& aDelta )
|
||||||
|| aItem->Type() == PCB_ARC_T
|
|| aItem->Type() == PCB_ARC_T
|
||||||
|| aItem->Type() == PCB_ZONE_T
|
|| aItem->Type() == PCB_ZONE_T
|
||||||
|| aItem->Type() == PCB_FOOTPRINT_T
|
|| aItem->Type() == PCB_FOOTPRINT_T
|
||||||
|| aItem->Type() == PCB_VIA_T );
|
|| aItem->Type() == PCB_VIA_T
|
||||||
|
|| aItem->Type() == PCB_SHAPE_T );
|
||||||
} ) )
|
} ) )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -153,6 +153,12 @@ int PCB_CONTROL::TrackDisplayMode( const TOOL_EVENT& aEvent )
|
||||||
view()->Update( track, KIGFX::REPAINT );
|
view()->Update( track, KIGFX::REPAINT );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for( BOARD_ITEM* shape : board()->Drawings() )
|
||||||
|
{
|
||||||
|
if( shape->Type() == PCB_SHAPE_T && static_cast<PCB_SHAPE*>( shape )->IsOnCopperLayer() )
|
||||||
|
view()->Update( shape, KIGFX::REPAINT );
|
||||||
|
}
|
||||||
|
|
||||||
canvas()->Refresh();
|
canvas()->Refresh();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1258,6 +1258,7 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks(
|
||||||
std::map<VECTOR2I, std::vector<PCB_TRACK*>> trackMap;
|
std::map<VECTOR2I, std::vector<PCB_TRACK*>> trackMap;
|
||||||
std::map<VECTOR2I, PCB_VIA*> viaMap;
|
std::map<VECTOR2I, PCB_VIA*> viaMap;
|
||||||
std::map<VECTOR2I, PAD*> padMap;
|
std::map<VECTOR2I, PAD*> padMap;
|
||||||
|
std::map<VECTOR2I, std::vector<PCB_SHAPE*>> shapeMap;
|
||||||
std::set<PAD*> startPadSet;
|
std::set<PAD*> startPadSet;
|
||||||
std::vector<BOARD_CONNECTED_ITEM*> cleanupItems;
|
std::vector<BOARD_CONNECTED_ITEM*> cleanupItems;
|
||||||
std::vector<std::pair<VECTOR2I, LSET>> activePts;
|
std::vector<std::pair<VECTOR2I, LSET>> activePts;
|
||||||
|
@ -1275,7 +1276,7 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks(
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto connectedItems = connectivity->GetConnectedItems( startItem,
|
auto connectedItems = connectivity->GetConnectedItems( startItem,
|
||||||
{ PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T }, true );
|
{ PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_SHAPE_T }, true );
|
||||||
|
|
||||||
// Build maps of connected items
|
// Build maps of connected items
|
||||||
for( BOARD_CONNECTED_ITEM* item : connectedItems )
|
for( BOARD_CONNECTED_ITEM* item : connectedItems )
|
||||||
|
@ -1305,6 +1306,16 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PCB_SHAPE_T:
|
||||||
|
{
|
||||||
|
PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
|
||||||
|
|
||||||
|
for( const auto& point : shape->GetConnectionPoints() )
|
||||||
|
shapeMap[point].push_back( shape );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1331,6 +1342,14 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks(
|
||||||
activePts.push_back( { startItem->GetPosition(), startItem->GetLayerSet() } );
|
activePts.push_back( { startItem->GetPosition(), startItem->GetLayerSet() } );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PCB_SHAPE_T:
|
||||||
|
{
|
||||||
|
PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( startItem );
|
||||||
|
|
||||||
|
for( const auto& point : shape->GetConnectionPoints() )
|
||||||
|
activePts.push_back( { point, startItem->GetLayerSet() } );
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1424,6 +1443,31 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for( PCB_SHAPE* shape : shapeMap[pt] )
|
||||||
|
{
|
||||||
|
if( !layerSetCu.Contains( shape->GetLayer() ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( !shape->IsSelected() )
|
||||||
|
select( shape );
|
||||||
|
|
||||||
|
if( !shape->HasFlag( SKIP_STRUCT ) )
|
||||||
|
{
|
||||||
|
shape->SetFlags( SKIP_STRUCT );
|
||||||
|
cleanupItems.push_back( shape );
|
||||||
|
|
||||||
|
for( const VECTOR2I& newPoint : shape->GetConnectionPoints() )
|
||||||
|
{
|
||||||
|
if( newPoint == pt )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
activePts.push_back( { newPoint, shape->GetLayerSet() } );
|
||||||
|
}
|
||||||
|
|
||||||
|
expand = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( viaMap.count( pt ) )
|
if( viaMap.count( pt ) )
|
||||||
{
|
{
|
||||||
PCB_VIA* via = viaMap[pt];
|
PCB_VIA* via = viaMap[pt];
|
||||||
|
|
|
@ -2947,11 +2947,11 @@ void APPEARANCE_CONTROLS::onObjectOpacitySlider( int aLayer, float aOpacity )
|
||||||
|
|
||||||
switch( aLayer )
|
switch( aLayer )
|
||||||
{
|
{
|
||||||
case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
|
case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
|
||||||
case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
|
case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
|
||||||
case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
|
case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
|
||||||
case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
|
case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
|
||||||
case static_cast<int>( LAYER_DRAW_BITMAPS ): options.m_ImageOpacity = aOpacity; break;
|
case static_cast<int>( LAYER_DRAW_BITMAPS ): options.m_ImageOpacity = aOpacity; break;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1108,12 +1108,14 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
||||||
knockoutTrackClearance( track );
|
knockoutTrackClearance( track );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add graphic item clearances. They are by definition unconnected, and have no clearance
|
// Add graphic item clearances.
|
||||||
// definitions of their own.
|
|
||||||
//
|
//
|
||||||
auto knockoutGraphicClearance =
|
auto knockoutGraphicClearance =
|
||||||
[&]( BOARD_ITEM* aItem )
|
[&]( BOARD_ITEM* aItem )
|
||||||
{
|
{
|
||||||
|
int shapeNet = ( aItem->Type() == PCB_SHAPE_T ) ? static_cast<PCB_SHAPE*>( aItem )->GetNetCode() : -1;
|
||||||
|
bool sameNet = shapeNet == aZone->GetNetCode() && aZone->GetNetCode() != 0;
|
||||||
|
|
||||||
// A item on the Edge_Cuts or Margin is always seen as on any layer:
|
// A item on the Edge_Cuts or Margin is always seen as on any layer:
|
||||||
if( aItem->IsOnLayer( aLayer )
|
if( aItem->IsOnLayer( aLayer )
|
||||||
|| aItem->IsOnLayer( Edge_Cuts )
|
|| aItem->IsOnLayer( Edge_Cuts )
|
||||||
|
@ -1125,7 +1127,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
||||||
int gap = evalRulesForItems( PHYSICAL_CLEARANCE_CONSTRAINT,
|
int gap = evalRulesForItems( PHYSICAL_CLEARANCE_CONSTRAINT,
|
||||||
aZone, aItem, aLayer );
|
aZone, aItem, aLayer );
|
||||||
|
|
||||||
if( aItem->IsOnLayer( aLayer ) )
|
if( aItem->IsOnLayer( aLayer ) && !sameNet )
|
||||||
{
|
{
|
||||||
gap = std::max( gap, evalRulesForItems( CLEARANCE_CONSTRAINT,
|
gap = std::max( gap, evalRulesForItems( CLEARANCE_CONSTRAINT,
|
||||||
aZone, aItem, aLayer ) );
|
aZone, aItem, aLayer ) );
|
||||||
|
@ -1142,7 +1144,8 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
||||||
aZone, aItem, Margin ) );
|
aZone, aItem, Margin ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
addKnockout( aItem, aLayer, gap + extra_margin, ignoreLineWidths, aHoles );
|
if( gap > 0 )
|
||||||
|
addKnockout( aItem, aLayer, gap + extra_margin, ignoreLineWidths, aHoles );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue