KiCad PCB EDA Suite
router_preview_item.cpp
Go to the documentation of this file.
1 /*
2  * KiRouter - a push-and-(sometimes-)shove PCB router
3  *
4  * Copyright (C) 2013-2014 CERN
5  * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
6  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <deque>
23 #include <gal/color4d.h>
24 
25 #include <geometry/shape_rect.h>
26 #include <geometry/shape_simple.h>
27 #include <pcb_painter.h>
28 
29 #include "router_preview_item.h"
30 
31 #include "pns_arc.h"
32 #include "pns_line.h"
33 #include "pns_segment.h"
34 #include "pns_via.h"
35 
36 using namespace KIGFX;
37 
40 {
41  m_view = aView;
42 
43  m_shape = aItem ? aItem->Shape()->Clone() : nullptr;
44 
45  m_clearance = -1;
47 
48  m_showTrackClearance = false;
49  m_showViaClearance = false;
50 
51  // initialize variables, overwritten by Update( aItem ), if aItem != NULL
52  m_router = NULL;
53  m_type = PR_SHAPE;
54  m_style = 0;
55  m_width = 0;
56  m_depth = 0;
57 
58  if( aItem )
59  Update( aItem );
60 }
61 
62 
64 {
65  delete m_shape;
66 }
67 
68 
70 {
71  m_originLayer = aItem->Layers().Start();
72 
73  if( aItem->OfKind( PNS::ITEM::LINE_T ) )
74  {
75  const PNS::LINE* l = static_cast<const PNS::LINE*>( aItem );
76 
77  if( !l->SegmentCount() )
78  return;
79  }
80 
81  assert( m_originLayer >= 0 );
82 
85  m_color.a = 0.8;
86  m_depth = BaseOverlayDepth - aItem->Layers().Start();
87 
88  switch( aItem->Kind() )
89  {
90  case PNS::ITEM::LINE_T:
91  m_type = PR_SHAPE;
92  m_width = static_cast<const PNS::LINE*>( aItem )->Width();
93  break;
94 
95  case PNS::ITEM::ARC_T:
96  m_type = PR_SHAPE;
97  m_width = static_cast<const PNS::ARC*>( aItem )->Width();
98  break;
99 
101  m_type = PR_SHAPE;
102  m_width = static_cast<const PNS::SEGMENT*>( aItem )->Width();
103  break;
104 
105  case PNS::ITEM::VIA_T:
107  m_type = PR_SHAPE;
108  m_width = 0;
109  m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 );
111  break;
112 
113  case PNS::ITEM::SOLID_T:
114  m_type = PR_SHAPE;
115  m_width = 0;
116  break;
117 
118  default:
119  break;
120  }
121 
122  if( aItem->Marker() & PNS::MK_VIOLATION )
123  m_color = COLOR4D( 0, 1, 0, 1 );
124 }
125 
126 
128 {
129  BOX2I bbox;
130 
131  switch( m_type )
132  {
133  case PR_SHAPE:
134  if( m_shape )
135  {
136  bbox = m_shape->BBox();
137  bbox.Inflate( m_width / 2 );
138  }
139  return bbox;
140 
141  case PR_POINT:
142  bbox = BOX2I ( m_pos - VECTOR2I( 100000, 100000 ), VECTOR2I( 200000, 200000 ) );
143  return bbox;
144 
145  default:
146  break;
147  }
148 
149  return bbox;
150 }
151 
152 
154 {
155  gal->SetIsFill( false );
156 
157  for( int s = 0; s < aL->GetSegmentCount(); s++ )
158  gal->DrawLine( aL->GetSegment( s ).A, aL->GetSegment( s ).B );
159 
160  const SHAPE_LINE_CHAIN* lineChain = dynamic_cast<const SHAPE_LINE_CHAIN*>( aL );
161 
162  for( size_t s = 0; lineChain && s < lineChain->ArcCount(); s++ )
163  {
164  const SHAPE_ARC& arc = lineChain->CArcs()[s];
165 
166  double start_angle = DEG2RAD( arc.GetStartAngle() );
167  double angle = DEG2RAD( arc.GetCentralAngle() );
168 
169  gal->DrawArc( arc.GetCenter(), arc.GetRadius(), start_angle, start_angle + angle);
170  }
171 
172  if( aL->IsClosed() )
173  gal->DrawLine( aL->GetSegment( -1 ).B, aL->GetSegment( 0 ).A );
174 }
175 
176 
177 void ROUTER_PREVIEW_ITEM::drawShape( const SHAPE* aShape, KIGFX::GAL* gal ) const
178 {
179  switch( aShape->Type() )
180  {
182  {
183  const SHAPE_LINE_CHAIN_BASE* l = (const SHAPE_LINE_CHAIN_BASE*) aShape;
184 
185  if( m_showTrackClearance && m_clearance > 0 )
186  {
187  gal->SetLineWidth( m_width + 2 * m_clearance );
188  drawLineChain( l, gal );
189  }
190 
191  gal->SetLayerDepth( m_depth );
192  gal->SetLineWidth( m_width );
193  gal->SetStrokeColor( m_color );
194  gal->SetFillColor( m_color );
195  drawLineChain( l, gal );
196  break;
197  }
198 
199  case SH_LINE_CHAIN:
200  {
201  const SHAPE_LINE_CHAIN* l = (const SHAPE_LINE_CHAIN*) aShape;
202  const int w = l->Width();
203 
204  if( m_showTrackClearance && m_clearance > 0 )
205  {
206  gal->SetLineWidth( w + 2 * m_clearance );
207  drawLineChain( l, gal );
208  }
209 
210  gal->SetLayerDepth( m_depth );
211  gal->SetLineWidth( w );
212  gal->SetStrokeColor( m_color );
213  gal->SetFillColor( m_color );
214  drawLineChain( l, gal );
215  break;
216  }
217 
218  case SH_SEGMENT:
219  {
220  const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) aShape;
221  const int w = s->GetWidth();
222 
223  if( m_showTrackClearance && m_clearance > 0 )
224  {
225  gal->SetLineWidth( w + 2 * m_clearance );
226  gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() + 2 * m_clearance );
227  }
228 
229  gal->SetLayerDepth( m_depth );
230  gal->SetLineWidth( w );
231  gal->SetStrokeColor( m_color );
232  gal->SetFillColor( m_color );
233  gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() );
234  break;
235  }
236 
237  case SH_CIRCLE:
238  {
239  const SHAPE_CIRCLE* c = (const SHAPE_CIRCLE*) aShape;
240  gal->SetStrokeColor( m_color );
241 
242  if( m_showViaClearance && m_clearance > 0 )
243  {
244  gal->SetIsStroke( false );
245  gal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance );
246  }
247 
248  gal->SetLayerDepth( m_depth );
249  gal->SetIsStroke( m_width ? true : false );
250  gal->SetLineWidth( m_width );
251  gal->SetFillColor( m_color );
252  gal->DrawCircle( c->GetCenter(), c->GetRadius() );
253 
254  break;
255  }
256 
257  case SH_RECT:
258  {
259  const SHAPE_RECT* r = (const SHAPE_RECT*) aShape;
260  gal->SetFillColor( m_color );
261 
262  if( m_clearance > 0 )
263  {
264  VECTOR2I p0( r->GetPosition() ), s( r->GetSize() );
265  gal->SetIsStroke( true );
266  gal->SetLineWidth( 2 * m_clearance );
267  gal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) );
268  gal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) );
269  gal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) );
270  gal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) );
271  }
272 
273  gal->SetLayerDepth( m_depth );
274  gal->SetIsStroke( m_width ? true : false );
275  gal->SetLineWidth( m_width);
276  gal->SetStrokeColor( m_color );
277  gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
278 
279  break;
280  }
281 
282  case SH_SIMPLE:
283  {
284  const SHAPE_SIMPLE* c = (const SHAPE_SIMPLE*) aShape;
285  std::deque<VECTOR2D> polygon = std::deque<VECTOR2D>();
286 
287  for( int i = 0; i < c->PointCount(); i++ )
288  {
289  polygon.push_back( c->CDPoint( i ) );
290  }
291 
292  gal->SetFillColor( m_color );
293 
294  if( m_clearance > 0 )
295  {
296  gal->SetIsStroke( true );
297  gal->SetLineWidth( 2 * m_clearance );
298  // need the implicit last segment to be explicit for DrawPolyline
299  polygon.push_back( c->CDPoint( 0 ) );
300  gal->DrawPolyline( polygon );
301  }
302 
303  gal->SetLayerDepth( m_depth );
304  gal->SetIsStroke( m_width ? true : false );
305  gal->SetLineWidth( m_width );
306  gal->SetStrokeColor( m_color );
307  gal->DrawPolygon( polygon );
308  break;
309  }
310 
311  case SH_ARC:
312  {
313  const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape );
314  const int w = arc->GetWidth();
315 
316  auto start_angle = DEG2RAD( arc->GetStartAngle() );
317  auto angle = DEG2RAD( arc->GetCentralAngle() );
318 
319  gal->SetIsFill( false );
320  gal->SetIsStroke( true );
321 
322  if( m_showTrackClearance && m_clearance > 0 )
323  {
324  gal->SetLineWidth( w + 2 * m_clearance );
325  gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle );
326  }
327 
328  gal->SetLayerDepth( m_depth );
329  gal->SetStrokeColor( m_color );
330  gal->SetFillColor( m_color );
331  gal->SetLineWidth( w );
332  gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle );
333  break;
334  }
335 
336  case SH_COMPOUND:
337  wxFAIL_MSG( "Router preview item: nested compound shapes not supported" );
338  break;
339 
340  case SH_POLY_SET:
341  wxFAIL_MSG( "Router preview item: SHAPE_POLY_SET not supported" );
342  break;
343 
344  case SH_NULL:
345  break;
346  }
347 }
348 
349 
350 void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
351 {
352  GAL* gal = aView->GetGAL();
353  //col.Brighten(0.7);
354 
355  if( m_type == PR_SHAPE )
356  {
357  if( !m_shape )
358  return;
359 
360  // N.B. The order of draw here is important
361  // Cairo doesn't current support z-ordering, so we need
362  // to draw the clearance first to ensure it is in the background
364  //TODO(snh) Add configuration option for the color/alpha here
365  gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.9 ) );
366  gal->SetFillColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.7 ) );
367  gal->SetIsStroke( m_width ? true : false );
368  gal->SetIsFill( true );
369 
371  {
372  std::vector<SHAPE*> subshapes;
373  m_shape->GetIndexableSubshapes( subshapes );
374 
375  for( SHAPE* shape : subshapes )
376  drawShape( shape, gal );
377  }
378  else
379  {
380  drawShape( m_shape, gal );
381  }
382  }
383 }
384 
385 
386 void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int aStyle )
387 {
388  m_width = aWidth;
389  m_color = assignColor( aStyle );
390  m_type = PR_SHAPE;
391  m_depth = -1024; // TODO gal->GetMinDepth()
392 
393  SHAPE_LINE_CHAIN *lc = static_cast<SHAPE_LINE_CHAIN*>( aLine.Clone() );
394  lc->SetWidth( aWidth );
395  m_shape = lc;
396 }
397 
398 
399 void ROUTER_PREVIEW_ITEM::Point( const VECTOR2I& aPos, int aStyle )
400 {
401 }
402 
403 
404 void ROUTER_PREVIEW_ITEM::Box( const BOX2I& aBox, int aStyle )
405 {
406 }
407 
408 
410 {
411  auto settings = static_cast<PCB_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() );
412 
413  return settings->GetLayerColor( aLayer );
414 }
415 
416 
417 const COLOR4D ROUTER_PREVIEW_ITEM::assignColor( int aStyle ) const
418 {
419  COLOR4D color;
420 
421  switch( aStyle )
422  {
423  case 0:
424  color = COLOR4D( 0, 1, 0, 1 ); break;
425 
426  case 1:
427  color = COLOR4D( 1, 0, 0, 1 ); break;
428 
429  case 2:
430  color = COLOR4D( 1, 1, 0, 1 ); break;
431 
432  case 3:
433  color = COLOR4D( 0, 0, 1, 1 ); break;
434 
435  case 4:
436  color = COLOR4D( 1, 1, 1, 1 ); break;
437 
438  case 5:
439  color = COLOR4D( 1, 1, 0, 1 ); break;
440 
441  case 6:
442  color = COLOR4D( 0, 1, 1, 1 ); break;
443 
444  case 32:
445  color = COLOR4D( 0, 0, 1, 1 ); break;
446 
447  default:
448  color = COLOR4D( 0.4, 0.4, 0.4, 1 ); break;
449  }
450 
451  return color;
452 }
453 
454 const int ROUTER_PREVIEW_ITEM::ClearanceOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 10;
455 const int ROUTER_PREVIEW_ITEM::BaseOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 20;
456 const int ROUTER_PREVIEW_ITEM::ViaOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 50;
compound shape, consisting of multiple simple shapes
Definition: shape.h:49
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
Base class for PNS router board items.
Definition: pns_item.h:55
virtual void DrawPolyline(const std::deque< VECTOR2D > &aPointList)
Draw a polyline.
void drawShape(const SHAPE *aShape, KIGFX::GAL *aGal) const
static const int ClearanceOverlayDepth
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a rectangle.
BOX2< VECTOR2I > BOX2I
Definition: box2.h:522
SHAPE_SIMPLE.
Definition: shape_simple.h:43
void drawLineChain(const SHAPE_LINE_CHAIN_BASE *aL, KIGFX::GAL *aGal) const
int GetRadius() const
Definition: shape_circle.h:107
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:175
int SegmentCount() const
Definition: pns_line.h:139
static const int BaseOverlayDepth
double GetRadius() const
Definition: shape_arc.cpp:402
virtual void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, double aStartAngle, double aEndAngle)
Draw an arc.
virtual bool IsClosed() const =0
the 3d code uses this value
Definition: typeinfo.h:79
int color
Definition: DXF_plotter.cpp:60
int Width() const
Gets the current width of the segments in the chain.
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:189
double GetStartAngle() const
Definition: shape_arc.cpp:363
const VECTOR2I GetCenter() const
Definition: shape_circle.h:112
size_t ArcCount() const
void Line(const SHAPE_LINE_CHAIN &aLine, int aWidth=0, int aStyle=0)
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:60
virtual size_t GetSegmentCount() const =0
const std::vector< SHAPE_ARC > & CArcs() const
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
virtual void SetLayerDepth(double aLayerDepth)
Set the depth of the layer (position on the z-axis)
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:207
const KIGFX::COLOR4D getLayerColor(int aLayer) const
const SEG & GetSeg() const
virtual void SetLineWidth(float aLineWidth)
Set the line width.
int Start() const
Definition: pns_layerset.h:82
const VECTOR2I GetSize() const
Definition: shape_rect.h:124
void SetWidth(int aWidth)
Sets the width of all segments in the chain.
const VECTOR2D CDPoint(int aIndex) const
Function CDPoint()
Definition: shape_simple.h:120
double a
Alpha component.
Definition: color4d.h:361
virtual void DrawSegment(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, double aWidth)
Draw a rounded segment.
#define NULL
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
virtual const SHAPE * Shape() const
Return the geometrical shape of the item.
Definition: pns_item.h:196
const VECTOR2I & GetPosition() const
Definition: shape_rect.h:116
void Update(const PNS::ITEM *aItem)
const KIGFX::COLOR4D assignColor(int aStyle) const
virtual SHAPE * Clone() const
Return a dynamically allocated copy of the shape.
Definition: shape.h:139
circular arc
Definition: shape.h:50
An abstract shape on 2D plane.
Definition: shape.h:116
virtual void ViewDraw(int aLayer, KIGFX::VIEW *aView) const override
Draw the parts of the object belonging to layer aLayer.
circle
Definition: shape.h:46
void Point(const VECTOR2I &aPos, int aStyle=0)
virtual const SEG GetSegment(int aIndex) const =0
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:302
int GetWidth() const
Definition: shape_arc.h:112
set of polygons (with holes, etc.)
Definition: shape.h:48
virtual void DrawPolygon(const std::deque< VECTOR2D > &aPointList)
Draw a polygon.
a single triangle belonging to a POLY_SET triangulation
Definition: shape.h:52
Meta control for all vias opacity/visibility.
virtual void GetIndexableSubshapes(std::vector< SHAPE * > &aSubshapes)
Definition: shape.h:106
virtual void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius)
Draw a circle using world coordinates.
double DEG2RAD(double deg)
Definition: trigo.h:231
SHAPE_LINE_CHAIN.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
VECTOR2I A
Definition: seg.h:49
bool OfKind(int aKindMask) const
Return true if the item's type matches the mask aKindMask.
Definition: pns_item.h:134
int PointCount() const
Function PointCount()
Definition: shape_simple.h:93
double GetCentralAngle() const
Definition: shape_arc.cpp:389
empty shape (no shape...),
Definition: shape.h:51
currently selected items overlay
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:150
line chain (polyline)
Definition: shape.h:45
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:126
SHAPE * Clone() const override
Return a dynamically allocated copy of the shape.
virtual bool HasIndexableSubshapes() const
Definition: shape.h:99
axis-aligned rectangle
Definition: shape.h:43
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
static const int ViaOverlayDepth
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
int GetWidth() const
simple polygon
Definition: shape.h:47
SHAPE_TYPE Type() const
Return the type of the shape.
Definition: shape.h:94
void Box(const BOX2I &aBox, int aStyle=0)
VECTOR2I GetCenter() const
Definition: shape_arc.cpp:383
ROUTER_PREVIEW_ITEM(const PNS::ITEM *aItem=NULL, KIGFX::VIEW *aView=NULL)
const LAYER_RANGE & Layers() const
Definition: pns_item.h:150
virtual int Marker() const
Definition: pns_item.h:208
line segment
Definition: shape.h:44
Abstract interface for drawing on a 2D-surface.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98
VECTOR2I B
Definition: seg.h:50