KiCad PCB EDA Suite
ratsnest_view_item.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KICAD, a free EDA CAD application.
3  *
4  * Copyright (C) 2013 CERN
5  * Copyright (C) 2018-2019 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * @author Maciej Suminski <maciej.suminski@cern.ch>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
32 
34 #include <pcb_painter.h>
35 #include <ratsnest/ratsnest_data.h>
36 
37 #include <layer_ids.h>
38 #include <pcb_base_frame.h>
39 
40 #include <memory>
41 #include <utility>
42 
43 #include <view/view.h>
44 
45 RATSNEST_VIEW_ITEM::RATSNEST_VIEW_ITEM( std::shared_ptr<CONNECTIVITY_DATA> aData ) :
46  EDA_ITEM( NOT_USED ), m_data( std::move(aData) )
47 {
48 }
49 
50 
52 {
53  // Make it always visible
54  BOX2I bbox;
55  bbox.SetMaximum();
56 
57  return bbox;
58 }
59 
60 
61 void RATSNEST_VIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
62 {
63  std::unique_lock<KISPINLOCK> lock( m_data->GetLock(), std::try_to_lock );
64 
65  if( !lock )
66  return;
67 
68  constexpr int CROSS_SIZE = 200000;
69 
70  auto gal = aView->GetGAL();
71  gal->SetIsStroke( true );
72  gal->SetIsFill( false );
73  gal->SetLineWidth( 1.0 );
74  auto rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( aView->GetPainter()->GetSettings() );
75 
76  COLOR4D defaultColor = rs->GetColor( nullptr, LAYER_RATSNEST );
77  COLOR4D color = defaultColor;
78  const bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF;
79 
80  std::set<int> highlightedNets = rs->GetHighlightNetCodes();
81  const std::set<int>& hiddenNets = rs->GetHiddenNets();
82 
83  std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
84  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
85  const std::map<int, wxString>& netclassMap = m_data->GetNetclassMap();
86 
87  const bool onlyVisibleLayers = rs->GetRatsnestDisplayMode() == RATSNEST_MODE::VISIBLE;
88 
89  LSET visibleLayers;
90 
91  // If we are in "other layers off" mode, the active layer is the only visible layer
92  if( rs->GetContrastModeDisplay() == HIGH_CONTRAST_MODE::HIDDEN )
93  {
94  visibleLayers.set( rs->GetPrimaryHighContrastLayer() );
95  }
96  else
97  {
98  for( PCB_LAYER_ID layer : LSET::AllCuMask().Seq() )
99  if( aView->IsLayerVisible( layer ) )
100  visibleLayers.set( layer );
101  }
102 
103  const bool curved_ratsnest = rs->GetCurvedRatsnestLinesEnabled();
104 
105  // Draw the "dynamic" ratsnest (i.e. for objects that may be currently being moved)
106  for( const RN_DYNAMIC_LINE& l : m_data->GetDynamicRatsnest() )
107  {
108  if( hiddenNets.count( l.netCode ) )
109  continue;
110 
111  if( colorByNet && netColors.count( l.netCode ) )
112  color = netColors.at( l.netCode );
113  else if( colorByNet && netclassMap.count( l.netCode )
114  && netclassColors.count( netclassMap.at( l.netCode ) ) )
115  color = netclassColors.at( netclassMap.at( l.netCode ) );
116  else
117  color = defaultColor;
118 
119  if( color == COLOR4D::UNSPECIFIED )
120  color = defaultColor;
121 
122  gal->SetStrokeColor( color.Brightened( 0.5 ) );
123 
124  if ( l.a == l.b )
125  {
126  gal->DrawLine( VECTOR2I( l.a.x - CROSS_SIZE, l.a.y - CROSS_SIZE ),
127  VECTOR2I( l.b.x + CROSS_SIZE, l.b.y + CROSS_SIZE ) );
128  gal->DrawLine( VECTOR2I( l.a.x - CROSS_SIZE, l.a.y + CROSS_SIZE ),
129  VECTOR2I( l.b.x + CROSS_SIZE, l.b.y - CROSS_SIZE ) );
130  }
131  else
132  {
133  if( curved_ratsnest )
134  {
135  auto dx = l.b.x - l.a.x;
136  auto dy = l.b.y - l.a.y;
137  const auto center = VECTOR2I( l.a.x + 0.5 * dx - 0.1 * dy,
138  l.a.y + 0.5 * dy + 0.1 * dx );
139  gal->DrawCurve( l.a, center, center, l.b );
140  }
141  else
142  {
143  gal->DrawLine( l.a, l.b );
144  }
145  }
146  }
147 
148  for( int i = 1 /* skip "No Net" at [0] */; i < m_data->GetNetCount(); ++i )
149  {
150  if( hiddenNets.count( i ) )
151  continue;
152 
153  RN_NET* net = m_data->GetRatsnestForNet( i );
154 
155  if( !net )
156  continue;
157 
158  if( colorByNet && netColors.count( i ) )
159  color = netColors.at( i );
160  else if( colorByNet && netclassMap.count( i )
161  && netclassColors.count( netclassMap.at( i ) ) )
162  color = netclassColors.at( netclassMap.at( i ) );
163  else
164  color = defaultColor;
165 
166  if( color == COLOR4D::UNSPECIFIED )
167  color = defaultColor;
168 
169  // Draw the "static" ratsnest
170  if( highlightedNets.count( i ) )
171  gal->SetStrokeColor( color.Brightened(0.8) );
172  else
173  gal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted
174 
175  for( const auto& edge : net->GetUnconnected() )
176  {
177  //if ( !edge.IsVisible() )
178  // continue;
179 
180  const auto& sourceNode = edge.GetSourceNode();
181  const auto& targetNode = edge.GetTargetNode();
182  const VECTOR2I source( sourceNode->Pos() );
183  const VECTOR2I target( targetNode->Pos() );
184 
185  if( !sourceNode->Valid() || !targetNode->Valid() )
186  continue;
187 
188  bool enable = !sourceNode->GetNoLine() && !targetNode->GetNoLine();
189  bool show;
190 
191  // If the global ratsnest is currently enabled, the local ratsnest
192  // should be easy to turn off, so either element can disable it
193  // If the global ratsnest is disabled, the local ratsnest should be easy to turn on
194  // so either element can enable it.
195  if( rs->GetGlobalRatsnestLinesEnabled() )
196  show = sourceNode->Parent()->GetLocalRatsnestVisible() &&
197  targetNode->Parent()->GetLocalRatsnestVisible();
198  else
199  show = sourceNode->Parent()->GetLocalRatsnestVisible() ||
200  targetNode->Parent()->GetLocalRatsnestVisible();
201 
202  if( onlyVisibleLayers && show )
203  {
204  LSET sourceLayers = sourceNode->Parent()->GetLayerSet();
205  LSET targetLayers = targetNode->Parent()->GetLayerSet();
206 
207  if( !( sourceLayers & visibleLayers ).any() ||
208  !( targetLayers & visibleLayers ).any() )
209  show = false;
210  }
211 
212  if ( enable && show )
213  {
214  if ( source == target )
215  {
216  gal->DrawLine( VECTOR2I( source.x - CROSS_SIZE, source.y - CROSS_SIZE ),
217  VECTOR2I( source.x + CROSS_SIZE, source.y + CROSS_SIZE ) );
218  gal->DrawLine( VECTOR2I( source.x - CROSS_SIZE, source.y + CROSS_SIZE ),
219  VECTOR2I( source.x + CROSS_SIZE, source.y - CROSS_SIZE ) );
220  }
221  else
222  {
223  if( curved_ratsnest )
224  {
225  auto dx = target.x - source.x;
226  auto dy = target.y - source.y;
227  const auto center = VECTOR2I( source.x + 0.5 * dx - 0.1 * dy,
228  source.y + 0.5 * dy + 0.1 * dx );
229  gal->DrawCurve( source, center, center, target );
230  }
231  else
232  {
233  gal->DrawLine( source, target );
234  }
235  }
236  }
237  }
238  }
239 }
240 
241 
242 void RATSNEST_VIEW_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const
243 {
244  aCount = 1;
245  aLayers[0] = LAYER_RATSNEST;
246 }
247 
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
const std::vector< CN_EDGE > GetUnconnected() const
Return pointer to a vector of edges that makes ratsnest for a given net.
Definition: ratsnest_data.h:98
Ratsnest lines are drawn to items on visible layers only.
void ViewGetLayers(int aLayers[], int &aCount) const override
Class that computes missing connections on a PCB.
the 3d code uses this value
Definition: typeinfo.h:79
int color
Definition: DXF_plotter.cpp:57
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:190
Definition: bitmap.cpp:64
RATSNEST_VIEW_ITEM(std::shared_ptr< CONNECTIVITY_DATA > aData)
Class that draws missing connections on a PCB.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:208
Classes used in Pcbnew, CvPcb and GerbView.
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:502
void SetMaximum()
Definition: box2.h:57
std::shared_ptr< CONNECTIVITY_DATA > m_data
Object containing ratsnest data.
const BOX2I ViewBBox() const override
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:64
Net (and netclass) colors are not shown.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
Describe ratsnest for a single net.
Definition: ratsnest_data.h:61
Inactive layers are hidden.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
void ViewDraw(int aLayer, KIGFX::VIEW *aView) const override
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:405
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103