KiCad PCB EDA Suite
class_edge_mod.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) 2015 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
7  * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
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 #include <fctsys.h>
33 #include <gr_basic.h>
34 #include <trigo.h>
35 #include <pcb_screen.h>
36 #include <confirm.h>
37 #include <kicad_string.h>
38 #include <richio.h>
39 #include <macros.h>
40 #include <math_for_graphics.h>
41 #include <pcb_base_frame.h>
42 #include <msgpanel.h>
43 #include <base_units.h>
44 #include <bitmaps.h>
45 
46 #include <pcb_edit_frame.h>
47 #include <class_board.h>
48 #include <class_module.h>
49 #include <class_edge_mod.h>
50 
51 #include <view/view.h>
52 
53 #include <stdio.h>
54 
57 {
58  m_Shape = aShape;
59  m_Angle = 0;
60  m_Layer = F_SilkS;
61 }
62 
63 
65 {
66 }
67 
68 
70 {
71  MODULE* module = (MODULE*) m_Parent;
72 
73  if( module == NULL )
74  {
75  m_Start0 = m_Start;
76  m_End0 = m_End;
79  return;
80  }
81 
82  m_Start0 = m_Start - module->GetPosition();
83  m_End0 = m_End - module->GetPosition();
84  m_Bezier0_C1 = m_BezierC1 - module->GetPosition();
85  m_Bezier0_C2 = m_BezierC2 - module->GetPosition();
86  double angle = module->GetOrientation();
87  RotatePoint( &m_Start0.x, &m_Start0.y, -angle );
88  RotatePoint( &m_End0.x, &m_End0.y, -angle );
91 }
92 
93 
95 {
96  MODULE* module = (MODULE*) m_Parent;
97 
98  m_Start = m_Start0;
99  m_End = m_End0;
102 
103  if( module )
104  {
105  RotatePoint( &m_Start.x, &m_Start.y, module->GetOrientation() );
106  RotatePoint( &m_End.x, &m_End.y, module->GetOrientation() );
107  RotatePoint( &m_BezierC1.x, &m_BezierC1.y, module->GetOrientation() );
108  RotatePoint( &m_BezierC2.x, &m_BezierC2.y, module->GetOrientation() );
109 
110  m_Start += module->GetPosition();
111  m_End += module->GetPosition();
112  m_BezierC1 += module->GetPosition();
113  m_BezierC2 += module->GetPosition();
114  }
115 
117 }
118 
119 
120 void EDGE_MODULE::Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& offset )
121 {
122  int ux0, uy0, dx, dy, radius, StAngle, EndAngle;
123  MODULE* module = (MODULE*) m_Parent;
124  BOARD* brd = GetBoard( );
125 
126  if( !module || !brd->IsLayerVisible( m_Layer ) )
127  return;
128 
129  auto color = aFrame->Settings().Colors().GetLayerColor( m_Layer );
130  auto displ_opts = (PCB_DISPLAY_OPTIONS*)( aFrame->GetDisplayOptions() );
131 
132  ux0 = m_Start.x - offset.x;
133  uy0 = m_Start.y - offset.y;
134 
135  dx = m_End.x - offset.x;
136  dy = m_End.y - offset.y;
137 
138  bool filled = displ_opts ? displ_opts->m_DisplayModEdgeFill : FILLED;
139 
140  if( IsCopperLayer( m_Layer ) )
141  filled = displ_opts ? displ_opts->m_DisplayPcbTrackFill : FILLED;
142 
143  switch( m_Shape )
144  {
145  case S_SEGMENT:
146  if( filled )
147  GRLine( nullptr, DC, ux0, uy0, dx, dy, m_Width, color );
148  else
149  // SKETCH Mode
150  GRCSegm( nullptr, DC, ux0, uy0, dx, dy, m_Width, color );
151 
152  break;
153 
154  case S_CIRCLE:
155  radius = KiROUND( Distance( ux0, uy0, dx, dy ) );
156 
157  if( filled )
158  {
159  GRCircle( nullptr, DC, ux0, uy0, radius, m_Width, color );
160  }
161  else // SKETCH Mode
162  {
163  GRCircle( nullptr, DC, ux0, uy0, radius + (m_Width / 2), color );
164  GRCircle( nullptr, DC, ux0, uy0, radius - (m_Width / 2), color );
165  }
166 
167  break;
168 
169  case S_ARC:
170  radius = KiROUND( Distance( ux0, uy0, dx, dy ) );
171  StAngle = ArcTangente( dy - uy0, dx - ux0 );
172  EndAngle = StAngle + m_Angle;
173 
174  if( StAngle > EndAngle )
175  std::swap( StAngle, EndAngle );
176 
177  if( filled )
178  {
179  GRArc( nullptr, DC, ux0, uy0, StAngle, EndAngle, radius, m_Width, color );
180  }
181  else // SKETCH Mode
182  {
183  GRArc( nullptr, DC, ux0, uy0, StAngle, EndAngle, radius + (m_Width / 2), color );
184  GRArc( nullptr, DC, ux0, uy0, StAngle, EndAngle, radius - (m_Width / 2), color );
185  }
186  break;
187 
188  case S_POLYGON:
189  if( m_Poly.IsEmpty() )
190  break;
191 
192  {
193  // We must compute absolute coordinates from m_PolyPoints
194  // which are relative to module position, orientation 0
195  std::vector<wxPoint> points;
196 
197  for( auto iter = m_Poly.CIterate(); iter; iter++ )
198  {
199  points.push_back( wxPoint( iter->x,iter->y ) );
200  }
201 
202  for( unsigned ii = 0; ii < points.size(); ii++ )
203  {
204  wxPoint& pt = points[ii];
205 
206  RotatePoint( &pt.x, &pt.y, module->GetOrientation() );
207  pt += module->GetPosition() - offset;
208  }
209 
210  GRPoly( nullptr, DC, points.size(), &points[0], true, m_Width, color, color );
211  }
212  break;
213 
214  case S_CURVE:
215  {
217 
218  wxPoint& startp = m_BezierPoints[0];
219 
220  for( unsigned int i = 1; i < m_BezierPoints.size(); i++ )
221  {
222  wxPoint& endp = m_BezierPoints[i];
223 
224  if( filled )
225  GRFilledSegment( nullptr, DC, startp-offset, endp-offset, m_Width, color );
226  else
227  GRCSegm( nullptr, DC, startp-offset, endp-offset, m_Width, color );
228 
229  startp = m_BezierPoints[i];
230  }
231  }
232  break;
233 
234  default:
235  break;
236  }
237 }
238 
239 
240 // see class_edge_mod.h
241 void EDGE_MODULE::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >& aList )
242 {
243  wxString msg;
244 
245  MODULE* module = (MODULE*) m_Parent;
246 
247  if( !module )
248  return;
249 
250  BOARD* board = (BOARD*) module->GetParent();
251 
252  if( !board )
253  return;
254 
255  aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), module->GetReference(), DARKCYAN ) );
256 
257  // append the features shared with the base class
258  DRAWSEGMENT::GetMsgPanelInfo( aUnits, aList );
259 }
260 
261 
262 
264 {
265  return wxString::Format( _( "Graphic %s of %s on %s" ),
266  ShowShape( m_Shape ),
267  ((MODULE*) GetParent())->GetReference(),
268  GetLayerName() );
269 }
270 
271 
272 BITMAP_DEF EDGE_MODULE::GetMenuImage() const
273 {
274  return show_mod_edge_xpm;
275 }
276 
277 
279 {
280  return new EDGE_MODULE( *this );
281 }
282 
283 
284 void EDGE_MODULE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
285 {
286  wxPoint pt;
287 
288  switch( GetShape() )
289  {
290  case S_ARC:
291  SetAngle( -GetAngle() );
292  //Fall through
293  default:
294  case S_SEGMENT:
295  case S_CURVE:
296  if( aFlipLeftRight )
297  {
298  MIRROR( m_Start.x, aCentre.x );
299  MIRROR( m_End.x, aCentre.x );
300  MIRROR( m_BezierC1.x, aCentre.x );
301  MIRROR( m_BezierC2.x, aCentre.x );
302  MIRROR( m_Start0.x, 0 );
303  MIRROR( m_End0.x, 0 );
304  MIRROR( m_Bezier0_C1.x, 0 );
305  MIRROR( m_Bezier0_C2.x, 0 );
306  }
307  else
308  {
309  MIRROR( m_Start.y, aCentre.y );
310  MIRROR( m_End.y, aCentre.y );
311  MIRROR( m_BezierC1.y, aCentre.y );
312  MIRROR( m_BezierC2.y, aCentre.y );
313  MIRROR( m_Start0.y, 0 );
314  MIRROR( m_End0.y, 0 );
315  MIRROR( m_Bezier0_C1.y, 0 );
316  MIRROR( m_Bezier0_C2.y, 0 );
317  }
318 
320  break;
321 
322  case S_POLYGON:
323  // polygon corners coordinates are always relative to the
324  // footprint position, orientation 0
325  for( auto iter = m_Poly.Iterate(); iter; iter++ )
326  {
327  if( aFlipLeftRight )
328  MIRROR( iter->x, 0 );
329  else
330  MIRROR( iter->y, 0 );
331  }
332  break;
333  }
334 
335  // DRAWSEGMENT items are not usually on copper layers, but
336  // it can happen in microwave apps.
337  // However, currently, only on Front or Back layers.
338  // So the copper layers count is not taken in account
339  SetLayer( FlipLayer( GetLayer() ) );
340 }
341 
343 {
344  if( GetParent() && GetParent()->GetLayer() == B_Cu )
345  return true;
346  return false;
347 }
348 
349 void EDGE_MODULE::Mirror( wxPoint aCentre, bool aMirrorAroundXAxis )
350 {
351  // Mirror an edge of the footprint. the layer is not modified
352  // This is a footprint shape modification.
353  switch( GetShape() )
354  {
355  case S_ARC:
356  SetAngle( -GetAngle() );
357  //Fall through
358  default:
359  case S_CURVE:
360  case S_SEGMENT:
361  if( aMirrorAroundXAxis )
362  {
363  MIRROR( m_Start0.y, aCentre.y );
364  MIRROR( m_End0.y, aCentre.y );
365  MIRROR( m_Bezier0_C1.y, aCentre.y );
366  MIRROR( m_Bezier0_C2.y, aCentre.y );
367  }
368  else
369  {
370  MIRROR( m_Start0.x, aCentre.x );
371  MIRROR( m_End0.x, aCentre.x );
372  MIRROR( m_Bezier0_C1.x, aCentre.x );
373  MIRROR( m_Bezier0_C2.x, aCentre.x );
374  }
375 
376  for( unsigned ii = 0; ii < m_BezierPoints.size(); ii++ )
377  {
378  if( aMirrorAroundXAxis )
379  MIRROR( m_BezierPoints[ii].y, aCentre.y );
380  else
381  MIRROR( m_BezierPoints[ii].x, aCentre.x );
382  }
383 
384  break;
385 
386  case S_POLYGON:
387  // polygon corners coordinates are always relative to the
388  // footprint position, orientation 0
389  for( auto iter = m_Poly.Iterate(); iter; iter++ )
390  {
391  if( aMirrorAroundXAxis )
392  MIRROR( iter->y, aCentre.y );
393  else
394  MIRROR( iter->x, aCentre.x );
395  }
396  }
397 
398  SetDrawCoord();
399 }
400 
401 void EDGE_MODULE::Rotate( const wxPoint& aRotCentre, double aAngle )
402 {
403  // We should rotate the relative coordinates, but to avoid duplicate code,
404  // do the base class rotation of draw coordinates, which is acceptable
405  // because in module editor, m_Pos0 = m_Pos
406  DRAWSEGMENT::Rotate( aRotCentre, aAngle );
407 
408  // and now update the relative coordinates, which are
409  // the reference in most transforms.
410  SetLocalCoord();
411 }
412 
413 
414 void EDGE_MODULE::Move( const wxPoint& aMoveVector )
415 {
416  // Move an edge of the footprint.
417  // This is a footprint shape modification.
418  m_Start0 += aMoveVector;
419  m_End0 += aMoveVector;
420  m_Bezier0_C1 += aMoveVector;
421  m_Bezier0_C2 += aMoveVector;
422 
423  switch( GetShape() )
424  {
425  default:
426  break;
427 
428  case S_POLYGON:
429  // polygon corners coordinates are always relative to the
430  // footprint position, orientation 0
431  for( auto iter = m_Poly.Iterate(); iter; iter++ )
432  *iter += VECTOR2I( aMoveVector );
433 
434  break;
435  }
436 
437  SetDrawCoord();
438 }
439 
440 unsigned int EDGE_MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
441 {
442  const int HIDE = std::numeric_limits<unsigned int>::max();
443 
444  if( !aView )
445  return 0;
446 
447  // Handle Render tab switches
448  if( !IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
449  return HIDE;
450 
451  if( IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
452  return HIDE;
453 
454  // Other layers are shown without any conditions
455  return 0;
456 }
wxPoint m_Bezier0_C2
Bezier Control Point 2, relative to module origin, orient 0.
static wxString ShowShape(STROKE_T aShape)
Function ShowShape converts the enum STROKE_T integer value to a wxString.
double GetOrientation() const
Definition: class_module.h:193
void GRPoly(EDA_RECT *ClipBox, wxDC *DC, int n, wxPoint Points[], bool Fill, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:546
EDA_ITEM * m_Parent
Linked list: Link (parent struct)
Definition: base_struct.h:180
virtual unsigned int ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:115
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
Implementation of conversion functions that require both schematic and board internal units.
This file is part of the common library.
STROKE_T GetShape() const
SHAPE_POLY_SET m_Poly
Stores the S_POLYGON shape.
int color
Definition: DXF_plotter.cpp:62
polygon (not yet used for tracks, but could be in microwave apps)
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Function FlippedLayerNumber.
Definition: lset.cpp:475
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_BezierPoints vertex list that approximate the Bezier curve by a list of segments Has me...
void GRCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, int aPenSize, COLOR4D Color)
Definition: gr_basic.cpp:312
usual segment : line with rounded ends
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
double m_Angle
Used only for Arcs: Arc angle in 1/10 deg.
ITERATOR Iterate(int aFirst, int aLast, bool aIterateHoles=false)
Function Iterate returns an object to iterate through the points of the polygons between aFirst and a...
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
void * GetDisplayOptions() override
Function GetDisplayOptions returns the display options current in use Display options are relative to...
wxPoint m_End0
End point, relative to module origin, orient 0.
This file contains miscellaneous commonly used macros and functions.
wxPoint m_BezierC1
Bezier Control Point 1.
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:407
wxPoint m_Bezier0_C1
Bezier Control Point 1, relative to module origin, orient 0.
Classes used in Pcbnew, CvPcb and GerbView.
show modules on front
void Rotate(const wxPoint &aRotCentre, double aAngle) override
Rotate an edge of the footprint.
bool IsParentFlipped() const
PCB_LAYER_ID m_Layer
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:123
COLOR4D GetLayerColor(LAYER_NUM aLayer) const
Function GetLayerColor.
void Mirror(const wxPoint aCentre, bool aMirrorAroundXAxis)
Mirror an edge of the footprint.
Class PCB_DISPLAY_OPTIONS handles display options like enable/disable some optional drawings.
wxPoint m_Start
Line start point or Circle and Arc center.
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:183
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
wxPoint m_End
Line end point or circle and arc start point.
PCB_GENERAL_SETTINGS & Settings()
Arcs (with rounded ends)
void GRArc(EDA_RECT *ClipBox, wxDC *DC, int xc, int yc, double StAngle, double EndAngle, int r, COLOR4D Color)
Definition: gr_basic.cpp:753
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
STROKE_T
Enum STROKE_T is the set of shapes for segments (graphic segments and tracks) which are often in the ...
STROKE_T m_Shape
Shape: line, Circle, Arc.
wxString GetSelectMenuText(EDA_UNITS_T aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Bezier Curve.
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color, wxPenStyle aStyle)
Definition: gr_basic.cpp:230
#define _(s)
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
COLORS_DESIGN_SETTINGS & Colors()
void Print(PCB_BASE_FRAME *aFrame, wxDC *DC, const wxPoint &offset=ZeroOffset) override
Function Print BOARD_ITEMs have their own color information.
void SetLocalCoord()
Set relative coordinates from draw coordinates.
double GetAngle() const
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
Function IsLayerVisible is a proxy function that calls the correspondent function in m_BoardSettings ...
Definition: class_board.h:459
virtual void Rotate(const wxPoint &aRotCentre, double aAngle) override
Function Rotate Rotate this object.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:161
void GRFilledSegment(EDA_RECT *aClipBox, wxDC *aDC, wxPoint aStart, wxPoint aEnd, int aWidth, COLOR4D aColor)
Definition: gr_basic.cpp:423
void Move(const wxPoint &aMoveVector) override
Move an edge of the footprint.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void GRCircle(EDA_RECT *ClipBox, wxDC *DC, int xc, int yc, int r, int width, COLOR4D Color)
Definition: gr_basic.cpp:600
size_t i
Definition: json11.cpp:597
EDGE_MODULE(MODULE *parent, STROKE_T aShape=S_SEGMENT)
void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
wxPoint m_BezierC2
Bezier Control Point 2.
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:163
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Flip entity relative to aCentre.
void GetMsgPanelInfo(EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
void SetAngle(double aAngle)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
void GetMsgPanelInfo(EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
int m_Width
thickness of lines ...
Module description (excepted pads)
wxPoint m_Start0
Start point or center, relative to module origin, orient 0.
Class EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
Class VIEW.
Definition: view.h:61
double Distance(double x1, double y1, double x2, double y2)
EDGE_MODULE class definition.
Message panel definition file.
BOARD_ITEM_CONTAINER * GetParent() const
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
const wxPoint GetPosition() const override
Definition: class_module.h:188
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
EDA_UNITS_T
Definition: common.h:154
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible() Returns information about visibility of a particular layer.
Definition: view.h:416
std::vector< wxPoint > m_BezierPoints