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 #include <view/view.h>
25 
26 #include <geometry/shape_rect.h>
27 #include <geometry/shape_simple.h>
28 #include "class_track.h"
29 #include <pcb_painter.h>
30 
31 #include "router_preview_item.h"
32 
33 #include "pns_arc.h"
34 #include "pns_line.h"
35 #include "pns_segment.h"
36 #include "pns_via.h"
37 
38 using namespace KIGFX;
39 
42 {
43  m_view = aView;
44 
45  m_shape = NULL;
46  m_clearance = -1;
48 
49  m_showTrackClearance = false;
50  m_showViaClearance = false;
51 
52  // initialize variables, overwritten by Update( aItem ), if aItem != NULL
53  m_router = NULL;
54  m_type = PR_SHAPE;
55  m_style = 0;
56  m_width = 0;
57  m_depth = 0;
58 
59  if( aItem )
60  Update( aItem );
61 }
62 
63 
65 {
66  delete m_shape;
67 }
68 
69 
71 {
72  m_originLayer = aItem->Layers().Start();
73 
74  if( aItem->OfKind( PNS::ITEM::LINE_T ) )
75  {
76  const PNS::LINE* l = static_cast<const PNS::LINE*>( aItem );
77 
78  if( !l->SegmentCount() )
79  return;
80  }
81 
82  assert( m_originLayer >= 0 );
83 
86  m_color.a = 0.8;
87  m_depth = BaseOverlayDepth - aItem->Layers().Start();
88 
89  if( ( aItem->Marker() & PNS::MK_ALT_SHAPE ) && aItem->AlternateShape() )
90  m_shape = aItem->AlternateShape()->Clone();
91  else
92  m_shape = aItem->Shape()->Clone();
93 
94  switch( aItem->Kind() )
95  {
96  case PNS::ITEM::LINE_T:
97  m_type = PR_SHAPE;
98  m_width = static_cast<const PNS::LINE*>( aItem )->Width();
99  break;
100 
101  case PNS::ITEM::ARC_T:
102  m_type = PR_SHAPE;
103  m_width = static_cast<const PNS::ARC*>( aItem )->Width();
104  break;
105 
107  m_type = PR_SHAPE;
108  m_width = static_cast<const PNS::SEGMENT*>( aItem )->Width();
109  break;
110 
111  case PNS::ITEM::VIA_T:
113  m_type = PR_SHAPE;
114  m_width = 0;
115  m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 );
117  break;
118 
119  case PNS::ITEM::SOLID_T:
120  m_type = PR_SHAPE;
121  m_width = 0;
122  break;
123 
124  default:
125  break;
126  }
127 
128  if( aItem->Marker() & PNS::MK_VIOLATION )
129  m_color = COLOR4D( 0, 1, 0, 1 );
130 }
131 
132 
134 {
135  BOX2I bbox;
136 
137  switch( m_type )
138  {
139  case PR_SHAPE:
140  if( m_shape )
141  {
142  bbox = m_shape->BBox();
143  bbox.Inflate( m_width / 2 );
144  }
145  return bbox;
146 
147  case PR_POINT:
148  bbox = BOX2I ( m_pos - VECTOR2I( 100000, 100000 ), VECTOR2I( 200000, 200000 ) );
149  return bbox;
150 
151  default:
152  break;
153  }
154 
155  return bbox;
156 }
157 
158 
160 {
161  gal->SetIsFill( false );
162 
163  for( int s = 0; s < aL->GetSegmentCount(); s++ )
164  gal->DrawLine( aL->GetSegment( s ).A, aL->GetSegment( s ).B );
165 
166  const SHAPE_LINE_CHAIN* lineChain = dynamic_cast<const SHAPE_LINE_CHAIN*>( aL );
167 
168  for( size_t s = 0; lineChain && s < lineChain->ArcCount(); s++ )
169  {
170  const SHAPE_ARC& arc = lineChain->CArcs()[s];
171 
172  double start_angle = DEG2RAD( arc.GetStartAngle() );
173  double angle = DEG2RAD( arc.GetCentralAngle() );
174 
175  gal->DrawArc( arc.GetCenter(), arc.GetRadius(), start_angle, start_angle + angle);
176  }
177 
178  if( aL->IsClosed() )
179  gal->DrawLine( aL->GetSegment( -1 ).B, aL->GetSegment( 0 ).A );
180 }
181 
182 
183 void ROUTER_PREVIEW_ITEM::drawShape( const SHAPE* aShape, KIGFX::GAL* gal ) const
184 {
185  switch( aShape->Type() )
186  {
188  {
189  const SHAPE_LINE_CHAIN_BASE* l = (const SHAPE_LINE_CHAIN_BASE*) aShape;
190 
191  if( m_showTrackClearance && m_clearance > 0 )
192  {
193  gal->SetLineWidth( m_width + 2 * m_clearance );
194  drawLineChain( l, gal );
195  }
196 
197  gal->SetLayerDepth( m_depth );
198  gal->SetLineWidth( m_width );
199  gal->SetStrokeColor( m_color );
200  gal->SetFillColor( m_color );
201  drawLineChain( l, gal );
202  break;
203  }
204 
205  case SH_LINE_CHAIN:
206  {
207  const SHAPE_LINE_CHAIN* l = (const SHAPE_LINE_CHAIN*) aShape;
208  const int w = l->Width();
209 
210  if( m_showTrackClearance && m_clearance > 0 )
211  {
212  gal->SetLineWidth( w + 2 * m_clearance );
213  drawLineChain( l, gal );
214  }
215 
216  gal->SetLayerDepth( m_depth );
217  gal->SetLineWidth( w );
218  gal->SetStrokeColor( m_color );
219  gal->SetFillColor( m_color );
220  drawLineChain( l, gal );
221  break;
222  }
223 
224  case SH_SEGMENT:
225  {
226  const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) aShape;
227  const int w = s->GetWidth();
228 
229  if( m_showTrackClearance && m_clearance > 0 )
230  {
231  gal->SetLineWidth( w + 2 * m_clearance );
232  gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() + 2 * m_clearance );
233  }
234 
235  gal->SetLayerDepth( m_depth );
236  gal->SetLineWidth( w );
237  gal->SetStrokeColor( m_color );
238  gal->SetFillColor( m_color );
239  gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() );
240  break;
241  }
242 
243  case SH_CIRCLE:
244  {
245  const SHAPE_CIRCLE* c = (const SHAPE_CIRCLE*) aShape;
246  gal->SetStrokeColor( m_color );
247 
248  if( m_showViaClearance && m_clearance > 0 )
249  {
250  gal->SetIsStroke( false );
251  gal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance );
252  }
253 
254  gal->SetLayerDepth( m_depth );
255  gal->SetIsStroke( m_width ? true : false );
256  gal->SetLineWidth( m_width );
257  gal->SetFillColor( m_color );
258  gal->DrawCircle( c->GetCenter(), c->GetRadius() );
259 
260  break;
261  }
262 
263  case SH_RECT:
264  {
265  const SHAPE_RECT* r = (const SHAPE_RECT*) aShape;
266  gal->SetFillColor( m_color );
267 
268  if( m_clearance > 0 )
269  {
270  VECTOR2I p0( r->GetPosition() ), s( r->GetSize() );
271  gal->SetIsStroke( true );
272  gal->SetLineWidth( 2 * m_clearance );
273  gal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) );
274  gal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) );
275  gal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) );
276  gal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) );
277  }
278 
279  gal->SetLayerDepth( m_depth );
280  gal->SetIsStroke( m_width ? true : false );
281  gal->SetLineWidth( m_width);
282  gal->SetStrokeColor( m_color );
283  gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
284 
285  break;
286  }
287 
288  case SH_SIMPLE:
289  {
290  const SHAPE_SIMPLE* c = (const SHAPE_SIMPLE*) aShape;
291  std::deque<VECTOR2D> polygon = std::deque<VECTOR2D>();
292 
293  for( int i = 0; i < c->PointCount(); i++ )
294  {
295  polygon.push_back( c->CDPoint( i ) );
296  }
297 
298  gal->SetFillColor( m_color );
299 
300  if( m_clearance > 0 )
301  {
302  gal->SetIsStroke( true );
303  gal->SetLineWidth( 2 * m_clearance );
304  // need the implicit last segment to be explicit for DrawPolyline
305  polygon.push_back( c->CDPoint( 0 ) );
306  gal->DrawPolyline( polygon );
307  }
308 
309  gal->SetLayerDepth( m_depth );
310  gal->SetIsStroke( m_width ? true : false );
311  gal->SetLineWidth( m_width );
312  gal->SetStrokeColor( m_color );
313  gal->DrawPolygon( polygon );
314  break;
315  }
316 
317  case SH_ARC:
318  {
319  const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape );
320  const int w = arc->GetWidth();
321 
322  auto start_angle = DEG2RAD( arc->GetStartAngle() );
323  auto angle = DEG2RAD( arc->GetCentralAngle() );
324 
325  gal->SetIsFill( false );
326  gal->SetIsStroke( true );
327 
328  if( m_showTrackClearance && m_clearance > 0 )
329  {
330  gal->SetLineWidth( w + 2 * m_clearance );
331  gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle );
332  }
333 
334  gal->SetLayerDepth( m_depth );
335  gal->SetStrokeColor( m_color );
336  gal->SetFillColor( m_color );
337  gal->SetLineWidth( w );
338  gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle );
339  break;
340  }
341 
342  case SH_COMPOUND:
343  wxFAIL_MSG( "Router preview item: nested compound shapes not supported" );
344  break;
345 
346  case SH_POLY_SET:
347  wxFAIL_MSG( "Router preview item: SHAPE_POLY_SET not supported" );
348  break;
349 
350  case SH_NULL:
351  break;
352  }
353 }
354 
355 
356 void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
357 {
358  GAL* gal = aView->GetGAL();
359  //col.Brighten(0.7);
360 
361  if( m_type == PR_SHAPE )
362  {
363  if( !m_shape )
364  return;
365 
366  // N.B. The order of draw here is important
367  // Cairo doesn't current support z-ordering, so we need
368  // to draw the clearance first to ensure it is in the background
370  //TODO(snh) Add configuration option for the color/alpha here
371  gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.9 ) );
372  gal->SetFillColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.7 ) );
373  gal->SetIsStroke( m_width ? true : false );
374  gal->SetIsFill( true );
375 
377  {
378  std::vector<SHAPE*> subshapes;
379  m_shape->GetIndexableSubshapes( subshapes );
380 
381  for( SHAPE* shape : subshapes )
382  drawShape( shape, gal );
383  }
384  else
385  {
386  drawShape( m_shape, gal );
387  }
388  }
389 }
390 
391 
392 void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int aStyle )
393 {
394  m_width = aWidth;
395  m_color = assignColor( aStyle );
396  m_type = PR_SHAPE;
397  m_depth = -1024; // TODO gal->GetMinDepth()
398  m_shape = aLine.Clone();
399 }
400 
401 
402 void ROUTER_PREVIEW_ITEM::Point( const VECTOR2I& aPos, int aStyle )
403 {
404 }
405 
406 
407 void ROUTER_PREVIEW_ITEM::Box( const BOX2I& aBox, int aStyle )
408 {
409 }
410 
411 
413 {
414  auto settings = static_cast<PCB_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() );
415 
416  return settings->GetLayerColor( aLayer );
417 }
418 
419 
420 const COLOR4D ROUTER_PREVIEW_ITEM::assignColor( int aStyle ) const
421 {
422  COLOR4D color;
423 
424  switch( aStyle )
425  {
426  case 0:
427  color = COLOR4D( 0, 1, 0, 1 ); break;
428 
429  case 1:
430  color = COLOR4D( 1, 0, 0, 1 ); break;
431 
432  case 2:
433  color = COLOR4D( 1, 1, 0, 1 ); break;
434 
435  case 3:
436  color = COLOR4D( 0, 0, 1, 1 ); break;
437 
438  case 4:
439  color = COLOR4D( 1, 1, 1, 1 ); break;
440 
441  case 5:
442  color = COLOR4D( 1, 1, 0, 1 ); break;
443 
444  case 6:
445  color = COLOR4D( 0, 1, 1, 1 ); break;
446 
447  case 32:
448  color = COLOR4D( 0, 0, 1, 1 ); break;
449 
450  default:
451  color = COLOR4D( 0.4, 0.4, 0.4, 1 ); break;
452  }
453 
454  return color;
455 }
456 
457 const int ROUTER_PREVIEW_ITEM::ClearanceOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 10;
458 const int ROUTER_PREVIEW_ITEM::BaseOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 20;
459 const int ROUTER_PREVIEW_ITEM::ViaOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 50;
set of polygons (with holes, etc.)
Definition: shape.h:49
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
ITEM.
Definition: pns_item.h:54
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:99
Class CAIRO_GAL is the cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:175
int SegmentCount() const
Returns the number of segments in the line
Definition: pns_line.h:155
static const int BaseOverlayDepth
double GetRadius() const
Definition: shape_arc.cpp:364
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:80
int color
Definition: DXF_plotter.cpp:60
int Width() const
Gets the current width of the segments in the chain.
GAL * GetGAL() const
Function GetGAL() Returns the GAL this view is using to draw graphical primitives.
Definition: view.h:182
double GetStartAngle() const
Definition: shape_arc.cpp:325
const VECTOR2I GetCenter() const
Definition: shape_circle.h:104
size_t ArcCount() const
void Line(const SHAPE_LINE_CHAIN &aLine, int aWidth=0, int aStyle=0)
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:594
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
Function BBox()
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:201
virtual const SHAPE * AlternateShape() const
Definition: pns_item.h:220
A single base class (TRACK) represents both tracks and vias, with subclasses for curved tracks (ARC) ...
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:83
const VECTOR2I GetSize() const
Function GetSize()
Definition: shape_rect.h:123
const VECTOR2D CDPoint(int aIndex) const
Function CDPoint()
Definition: shape_simple.h:120
double a
Alpha component.
Definition: color4d.h:377
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
Function Shape()
Definition: pns_item.h:215
const VECTOR2I & GetPosition() const
Function GetPosition()
Definition: shape_rect.h:113
void Update(const PNS::ITEM *aItem)
const KIGFX::COLOR4D assignColor(int aStyle) const
virtual SHAPE * Clone() const
Function Clone()
Definition: shape.h:148
compound shape, consisting of multiple simple shapes
Definition: shape.h:50
SHAPE.
Definition: shape.h:122
virtual void ViewDraw(int aLayer, KIGFX::VIEW *aView) const override
Function ViewDraw() Draws the parts of the object belonging to layer aLayer.
line chain (polyline)
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
Function GetAdapter Returns 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:102
simple polygon
Definition: shape.h:48
virtual void DrawPolygon(const std::deque< VECTOR2D > &aPointList)
Draw a polygon.
empty shape (no shape...),
Definition: shape.h:52
Meta control for all vias opacity/visibility.
virtual void GetIndexableSubshapes(std::vector< SHAPE * > &aSubshapes)
Definition: shape.h:110
virtual void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius)
Draw a circle using world coordinates.
double DEG2RAD(double deg)
Definition: trigo.h:220
SHAPE_LINE_CHAIN.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
VECTOR2I A
Definition: seg.h:47
bool OfKind(int aKindMask) const
Function OfKind()
Definition: pns_item.h:134
int PointCount() const
Function PointCount()
Definition: shape_simple.h:93
double GetCentralAngle() const
Definition: shape_arc.cpp:351
circular arc
Definition: shape.h:51
currently selected items overlay
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: eda_item.h:148
line segment
Definition: shape.h:45
const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers.
PnsKind Kind() const
Function Kind()
Definition: pns_item.h:124
SHAPE * Clone() const override
Function Clone()
virtual bool HasIndexableSubshapes() const
Definition: shape.h:103
Definition: shape.h:43
VIEW.
Definition: view.h:63
static const int ViaOverlayDepth
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
int GetWidth() const
circle
Definition: shape.h:47
SHAPE_TYPE Type() const
Function Type()
Definition: shape.h:98
void Box(const BOX2I &aBox, int aStyle=0)
VECTOR2I GetCenter() const
Definition: shape_arc.cpp:345
ROUTER_PREVIEW_ITEM(const PNS::ITEM *aItem=NULL, KIGFX::VIEW *aView=NULL)
const LAYER_RANGE & Layers() const
Definition: pns_item.h:152
virtual int Marker() const
Definition: pns_item.h:227
axis-aligned rectangle
Definition: shape.h:44
Class GAL is the abstract interface for drawing on a 2D-surface.
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:100
VECTOR2I B
Definition: seg.h:48