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-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
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>
27#include <pcb_painter.h>
28#include <trigo.h>
29
30#include "router_preview_item.h"
31
32#include "pns_arc.h"
33#include "pns_line.h"
34#include "pns_segment.h"
35#include "pns_via.h"
36
37using namespace KIGFX;
38
39
42{
43 m_view = aView;
44
45 m_shape = aItem ? aItem->Shape()->Clone() : nullptr;
46 m_hole = aItem && aItem->Hole() ? aItem->Hole()->Clone() : nullptr;
47
48 m_clearance = -1;
50
51 m_showClearance = false;
52
53 // initialize variables, overwritten by Update( aItem ), if aItem != NULL
55 m_width = 0;
56 m_depth = 0;
57 m_isHeadTrace = false;
58
59 if( aItem )
60 Update( aItem );
61}
62
63
66{
67 m_view = aView;
68
69 m_shape = aShape.Clone();
70 m_hole = nullptr;
71
72 m_clearance = -1;
74
75 m_showClearance = false;
76
77 // initialize variables, overwritten by Update( aItem ), if aItem != NULL
79 m_width = 0;
80 m_depth = 0;
81 m_isHeadTrace = false;
82}
83
84
86{
87 delete m_shape;
88 delete m_hole;
89}
90
91
93{
94 m_originLayer = aItem->Layers().Start();
95
96 if( const PNS::LINE* l = dyn_cast<const PNS::LINE*>( aItem ) )
97 {
98 if( !l->SegmentCount() )
99 return;
100 }
101 else if( const PNS::VIA* v = dyn_cast<const PNS::VIA*>( aItem ) )
102 {
103 if( v->IsVirtual() )
104 return;
105 }
106
107 assert( m_originLayer >= 0 );
108
111 m_color.a = 0.8;
112 m_depth = BaseOverlayDepth - aItem->Layers().Start();
113
114 switch( aItem->Kind() )
115 {
118 m_width = static_cast<const PNS::LINE*>( aItem )->Width();
119 break;
120
121 case PNS::ITEM::ARC_T:
123 m_width = static_cast<const PNS::ARC*>( aItem )->Width();
124 break;
125
128 m_width = static_cast<const PNS::SEGMENT*>( aItem )->Width();
129 break;
130
131 case PNS::ITEM::VIA_T:
134 m_width = 0;
135 m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 );
137
138 delete m_shape;
139 m_shape = nullptr;
140
141 if( aItem->Shape() )
142 m_shape = aItem->Shape()->Clone();
143
144 delete m_hole;
145 m_hole = nullptr;
146
147 if( aItem->Hole() )
148 m_hole = aItem->Hole()->Clone();
149
150 break;
151
154 m_width = 0;
155 break;
156
157 default:
158 break;
159 }
160
161 if( aItem->Marker() & PNS::MK_VIOLATION )
162 m_color = COLOR4D( 0, 1, 0, 1 );
163}
164
165
167{
168 BOX2I bbox;
169
170 switch( m_type )
171 {
172 case PR_SHAPE:
173 if( m_shape )
174 {
175 bbox = m_shape->BBox();
176 bbox.Inflate( m_width / 2 );
177 }
178
179 if( m_hole )
180 bbox.Merge( m_hole->BBox() );
181
182 return bbox;
183
184 case PR_POINT:
185 bbox = BOX2I ( m_pos - VECTOR2I( 100000, 100000 ), VECTOR2I( 200000, 200000 ) );
186 return bbox;
187
188 default:
189 break;
190 }
191
192 return bbox;
193}
194
195
197{
198 wxCHECK( aL, /* void */ );
199
200 gal->SetIsFill( false );
201
202 for( int s = 0; s < aL->GetSegmentCount(); s++ )
203 gal->DrawLine( aL->GetSegment( s ).A, aL->GetSegment( s ).B );
204
205 const SHAPE_LINE_CHAIN* lineChain = dynamic_cast<const SHAPE_LINE_CHAIN*>( aL );
206
207 for( size_t s = 0; lineChain && s < lineChain->ArcCount(); s++ )
208 {
209 const SHAPE_ARC& arc = lineChain->CArcs()[s];
210 EDA_ANGLE start_angle = arc.GetStartAngle();
212
213 gal->DrawArc( arc.GetCenter(), arc.GetRadius(), start_angle, start_angle + angle);
214 }
215
216 if( aL->IsClosed() )
217 gal->DrawLine( aL->GetSegment( -1 ).B, aL->GetSegment( 0 ).A );
218}
219
220
221void ROUTER_PREVIEW_ITEM::drawShape( const SHAPE* aShape, KIGFX::GAL* gal ) const
222{
223 bool holeDrawn = false;
224
225 switch( aShape->Type() )
226 {
228 {
229 const SHAPE_LINE_CHAIN_BASE* l = (const SHAPE_LINE_CHAIN_BASE*) aShape;
230
231 if( m_showClearance && m_clearance > 0 )
232 {
233 gal->SetLineWidth( m_width + 2 * m_clearance );
234 drawLineChain( l, gal );
235 }
236
237 gal->SetLayerDepth( m_depth );
238 gal->SetLineWidth( m_width );
239 gal->SetStrokeColor( m_color );
240 gal->SetFillColor( m_color );
241 drawLineChain( l, gal );
242 break;
243 }
244
245 case SH_LINE_CHAIN:
246 {
247 const SHAPE_LINE_CHAIN* l = (const SHAPE_LINE_CHAIN*) aShape;
248 const int w = m_width;
249
250 if( m_showClearance && m_clearance > 0 )
251 {
252 gal->SetLineWidth( w + 2 * m_clearance );
253 drawLineChain( l, gal );
254 }
255
256 gal->SetLayerDepth( m_depth );
257 gal->SetLineWidth( w );
258 gal->SetStrokeColor( m_color );
259 gal->SetFillColor( m_color );
260 drawLineChain( l, gal );
261 break;
262 }
263
264 case SH_SEGMENT:
265 {
266 const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) aShape;
267 const int w = s->GetWidth();
268
269 gal->SetIsStroke( false );
270
271 if( m_showClearance && m_clearance > 0 )
272 {
273 gal->SetLineWidth( w + 2 * m_clearance );
274 gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() + 2 * m_clearance );
275 }
276
277 gal->SetLayerDepth( m_depth );
278 gal->SetLineWidth( w );
279 gal->SetFillColor( m_color );
280 gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() );
281 break;
282 }
283
284 case SH_CIRCLE:
285 {
286 const SHAPE_CIRCLE* c = static_cast<const SHAPE_CIRCLE*>( aShape );
287 gal->SetStrokeColor( m_color );
288
289 if( m_showClearance && m_clearance > 0 )
290 {
291 gal->SetIsStroke( false );
292 gal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance );
293 }
294
295 gal->SetLayerDepth( m_depth );
296
297 if( m_hole && dynamic_cast<SHAPE_CIRCLE*>( m_hole ) )
298 {
299 const SHAPE_CIRCLE* h = static_cast<const SHAPE_CIRCLE*>( m_hole );
300 int halfWidth = m_width / 2;
301
302 gal->SetIsStroke( true );
303 gal->SetIsFill( false );
304 gal->SetLineWidth( halfWidth + c->GetRadius() - h->GetRadius() );
305 gal->DrawCircle( c->GetCenter(), ( halfWidth + c->GetRadius() + h->GetRadius() ) / 2 );
306
307 holeDrawn = true;
308 }
309 else
310 {
311 gal->SetIsStroke( m_width ? true : false );
312 gal->SetLineWidth( m_width );
313 gal->SetFillColor( m_color );
314 gal->DrawCircle( c->GetCenter(), c->GetRadius() );
315 }
316
317 break;
318 }
319
320 case SH_RECT:
321 {
322 const SHAPE_RECT* r = (const SHAPE_RECT*) aShape;
323 gal->SetFillColor( m_color );
324
325 if( m_showClearance && m_clearance > 0 )
326 {
327 VECTOR2I p0( r->GetPosition() ), s( r->GetSize() );
328 gal->SetIsStroke( true );
329 gal->SetLineWidth( 2 * m_clearance );
330 gal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) );
331 gal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) );
332 gal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) );
333 gal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) );
334 }
335
336 gal->SetLayerDepth( m_depth );
337 gal->SetIsStroke( m_width ? true : false );
338 gal->SetLineWidth( m_width);
339 gal->SetStrokeColor( m_color );
340 gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
341
342 break;
343 }
344
345 case SH_SIMPLE:
346 {
347 const SHAPE_SIMPLE* c = (const SHAPE_SIMPLE*) aShape;
348 std::deque<VECTOR2D> polygon = std::deque<VECTOR2D>();
349
350 for( int i = 0; i < c->PointCount(); i++ )
351 {
352 polygon.push_back( c->CDPoint( i ) );
353 }
354
355 gal->SetFillColor( m_color );
356
357 if( m_showClearance && m_clearance > 0 )
358 {
359 gal->SetIsStroke( true );
360 gal->SetLineWidth( 2 * m_clearance );
361
362 // need the implicit last segment to be explicit for DrawPolyline
363 polygon.push_back( c->CDPoint( 0 ) );
364 gal->DrawPolyline( polygon );
365 }
366
367 gal->SetLayerDepth( m_depth );
368 gal->SetIsStroke( m_width ? true : false );
369 gal->SetLineWidth( m_width );
370 gal->SetStrokeColor( m_color );
371 gal->DrawPolygon( polygon );
372 break;
373 }
374
375 case SH_ARC:
376 {
377 const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape );
378 const int w = arc->GetWidth();
379 EDA_ANGLE start_angle = arc->GetStartAngle();
381
382 gal->SetIsFill( false );
383 gal->SetIsStroke( true );
384
385 if( m_showClearance && m_clearance > 0 )
386 {
387 gal->SetLineWidth( w + 2 * m_clearance );
388 gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle );
389 }
390
391 gal->SetLayerDepth( m_depth );
392 gal->SetStrokeColor( m_color );
393 gal->SetFillColor( m_color );
394 gal->SetLineWidth( w );
395 gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle );
396 break;
397 }
398
399 case SH_COMPOUND:
400 wxFAIL_MSG( wxT( "Router preview item: nested compound shapes not supported" ) );
401 break;
402
403 case SH_POLY_SET:
404 wxFAIL_MSG( wxT( "Router preview item: SHAPE_POLY_SET not supported" ) );
405 break;
406
407 case SH_NULL:
408 break;
409 }
410
411 if( m_hole && !holeDrawn )
412 {
413 gal->SetLayerDepth( m_depth );
414 gal->SetIsStroke( true );
415 gal->SetIsFill( false );
416 gal->SetStrokeColor( m_color );
417 gal->SetLineWidth( 1 );
418
419 SHAPE_CIRCLE* circle = dynamic_cast<SHAPE_CIRCLE*>( m_hole );
420 SHAPE_SEGMENT* slot = dynamic_cast<SHAPE_SEGMENT*>( m_hole );
421
422 if( circle )
423 gal->DrawCircle( circle->GetCenter(), circle->GetRadius() );
424 else if( slot )
425 gal->DrawSegment( slot->GetSeg().A, slot->GetSeg().B, slot->GetWidth() );
426 }
427}
428
429
430void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
431{
432 GAL* gal = aView->GetGAL();
433 //col.Brighten(0.7);
434
435 if( m_type == PR_SHAPE )
436 {
437 if( !m_shape )
438 return;
439
440 // N.B. The order of draw here is important
441 // Cairo doesn't current support z-ordering, so we need
442 // to draw the clearance first to ensure it is in the background
444
445 //TODO(snh) Add configuration option for the color/alpha here
446 gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.9 ) );
447 gal->SetFillColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.7 ) );
448 gal->SetIsStroke( m_width ? true : false );
449 gal->SetIsFill( true );
450
452 {
453 std::vector<const SHAPE*> subshapes;
454 m_shape->GetIndexableSubshapes( subshapes );
455
456 for( const SHAPE* shape : subshapes )
457 drawShape( shape, gal );
458 }
459 else
460 {
461 drawShape( m_shape, gal );
462 }
463 }
464}
465
466
468{
469 auto settings = static_cast<PCB_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() );
470
471 COLOR4D color = settings->GetLayerColor( aLayer );
472
473 if( m_isHeadTrace )
474 {
475 return color.Saturate( 1.0 );
476 }
477
478 return color;
479}
480
481
483{
485
486 switch( aStyle )
487 {
488 case 0: color = COLOR4D( 0, 1, 0, 1 ); break;
489 case 1: color = COLOR4D( 1, 0, 0, 1 ); break;
490 case 2: color = COLOR4D( 1, 1, 0, 1 ); break;
491 case 3: color = COLOR4D( 0, 0, 1, 1 ); break;
492 case 4: color = COLOR4D( 1, 1, 1, 1 ); break;
493 case 5: color = COLOR4D( 1, 1, 0, 1 ); break;
494 case 6: color = COLOR4D( 0, 1, 1, 1 ); break;
495 case 32: color = COLOR4D( 0, 0, 1, 1 ); break;
496 default: color = COLOR4D( 0.4, 0.4, 0.4, 1 ); break;
497 }
498
499 return color;
500}
501
502const int ROUTER_PREVIEW_ITEM::ClearanceOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 10;
503const int ROUTER_PREVIEW_ITEM::BaseOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 20;
504const int ROUTER_PREVIEW_ITEM::ViaOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 50;
505const int ROUTER_PREVIEW_ITEM::PathOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 55;
int color
Definition: DXF_plotter.cpp:57
BOX2< VECTOR2I > BOX2I
Definition: box2.h:847
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:102
double a
Alpha component.
Definition: color4d.h:375
Abstract interface for drawing on a 2D-surface.
virtual void DrawPolygon(const std::deque< VECTOR2D > &aPointList)
Draw a polygon.
virtual void SetLayerDepth(double aLayerDepth)
Set the depth of the layer (position on the z-axis)
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a rectangle.
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
virtual void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius)
Draw a circle using world coordinates.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
virtual void DrawPolyline(const std::deque< VECTOR2D > &aPointList)
Draw a polyline.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
virtual void DrawSegment(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, double aWidth)
Draw a rounded segment.
virtual void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle)
Draw an arc.
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition: pcb_painter.h:72
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:195
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
int Start() const
Definition: pns_layerset.h:82
Base class for PNS router board items.
Definition: pns_item.h:56
virtual const SHAPE * Hole() const
Definition: pns_item.h:207
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:132
virtual const SHAPE * Shape() const
Return the geometrical shape of the item.
Definition: pns_item.h:202
@ SOLID_T
Definition: pns_item.h:63
@ LINE_T
Definition: pns_item.h:64
@ SEGMENT_T
Definition: pns_item.h:66
const LAYER_RANGE & Layers() const
Definition: pns_item.h:156
virtual int Marker() const
Definition: pns_item.h:214
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:61
const KIGFX::COLOR4D assignColor(int aStyle) const
ROUTER_PREVIEW_ITEM(const SHAPE &aShape, KIGFX::VIEW *aView=nullptr)
void Update(const PNS::ITEM *aItem)
const KIGFX::COLOR4D getLayerColor(int aLayer) const
static const int PathOverlayDepth
virtual void ViewDraw(int aLayer, KIGFX::VIEW *aView) const override
Draw the parts of the object belonging to layer aLayer.
static const int ClearanceOverlayDepth
static const int ViaOverlayDepth
static const int BaseOverlayDepth
void drawLineChain(const SHAPE_LINE_CHAIN_BASE *aL, KIGFX::GAL *aGal) const
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
void drawShape(const SHAPE *aShape, KIGFX::GAL *aGal) const
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
EDA_ANGLE GetCentralAngle() const
Definition: shape_arc.cpp:448
int GetWidth() const
Definition: shape_arc.h:157
double GetRadius() const
Definition: shape_arc.cpp:464
EDA_ANGLE GetStartAngle() const
Definition: shape_arc.cpp:419
VECTOR2I GetCenter() const
Definition: shape_arc.cpp:433
virtual void GetIndexableSubshapes(std::vector< const SHAPE * > &aSubshapes) const
Definition: shape.h:113
virtual bool HasIndexableSubshapes() const
Definition: shape.h:106
SHAPE_TYPE Type() const
Return the type of the shape.
Definition: shape.h:96
int GetRadius() const
Definition: shape_circle.h:108
const VECTOR2I GetCenter() const
Definition: shape_circle.h:113
virtual size_t GetSegmentCount() const =0
virtual bool IsClosed() const =0
virtual const SEG GetSegment(int aIndex) const =0
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const std::vector< SHAPE_ARC > & CArcs() const
size_t ArcCount() const
const VECTOR2I & GetPosition() const
Definition: shape_rect.h:127
const VECTOR2I GetSize() const
Definition: shape_rect.h:135
const SEG & GetSeg() const
int GetWidth() const
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:42
int PointCount() const
Return the number of points (vertices) in this polygon.
Definition: shape_simple.h:88
const VECTOR2D CDPoint(int aIndex) const
Return a given point as a vector with elements of type double.
Definition: shape_simple.h:113
An abstract shape on 2D plane.
Definition: shape.h:124
virtual SHAPE * Clone() const
Return a dynamically allocated copy of the shape.
Definition: shape.h:146
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.
@ DARKDARKGRAY
Definition: color4d.h:43
@ LAYER_SELECT_OVERLAY
currently selected items overlay
Definition: layer_ids.h:219
@ LAYER_VIAS
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:193
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:246
@ MK_VIOLATION
Definition: pns_item.h:42
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
@ SH_POLY_SET
set of polygons (with holes, etc.)
Definition: shape.h:50
@ SH_RECT
axis-aligned rectangle
Definition: shape.h:45
@ SH_CIRCLE
circle
Definition: shape.h:48
@ SH_SIMPLE
simple polygon
Definition: shape.h:49
@ SH_NULL
empty shape (no shape...),
Definition: shape.h:53
@ SH_SEGMENT
line segment
Definition: shape.h:46
@ SH_ARC
circular arc
Definition: shape.h:52
@ SH_POLY_SET_TRIANGLE
a single triangle belonging to a POLY_SET triangulation
Definition: shape.h:54
@ SH_LINE_CHAIN
line chain (polyline)
Definition: shape.h:47
@ SH_COMPOUND
compound shape, consisting of multiple simple shapes
Definition: shape.h:51
@ NOT_USED
the 3d code uses this value
Definition: typeinfo.h:79
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590