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( 0, 0 );
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 Start0 and Start are equal (ie: ModEdit), then flip both sets around the
297  // centre point.
298  if( m_Start == m_Start0 )
299  pt = aCentre;
300 
301  if( aFlipLeftRight )
302  {
303  MIRROR( m_Start.x, aCentre.x );
304  MIRROR( m_End.x, aCentre.x );
305  MIRROR( m_BezierC1.x, aCentre.x );
306  MIRROR( m_BezierC2.x, aCentre.x );
307  MIRROR( m_Start0.x, pt.x );
308  MIRROR( m_End0.x, pt.x );
309  MIRROR( m_Bezier0_C1.x, pt.x );
310  MIRROR( m_Bezier0_C2.x, pt.x );
311  }
312  else
313  {
314  MIRROR( m_Start.y, aCentre.y );
315  MIRROR( m_End.y, aCentre.y );
316  MIRROR( m_BezierC1.y, aCentre.y );
317  MIRROR( m_BezierC2.y, aCentre.y );
318  MIRROR( m_Start0.y, pt.y );
319  MIRROR( m_End0.y, pt.y );
320  MIRROR( m_Bezier0_C1.y, pt.y );
321  MIRROR( m_Bezier0_C2.y, pt.y );
322  }
323 
325  break;
326 
327  case S_POLYGON:
328  // polygon corners coordinates are always relative to the
329  // footprint position, orientation 0
330  for( auto iter = m_Poly.Iterate(); iter; iter++ )
331  {
332  if( aFlipLeftRight )
333  MIRROR( iter->x, 0 );
334  else
335  MIRROR( iter->y, 0 );
336  }
337  break;
338  }
339 
340  // DRAWSEGMENT items are not usually on copper layers, but
341  // it can happen in microwave apps.
342  // However, currently, only on Front or Back layers.
343  // So the copper layers count is not taken in account
344  SetLayer( FlipLayer( GetLayer() ) );
345 }
346 
348 {
349  if( GetParent() && GetParent()->GetLayer() == B_Cu )
350  return true;
351  return false;
352 }
353 
354 void EDGE_MODULE::Mirror( wxPoint aCentre, bool aMirrorAroundXAxis )
355 {
356  // Mirror an edge of the footprint. the layer is not modified
357  // This is a footprint shape modification.
358  switch( GetShape() )
359  {
360  case S_ARC:
361  SetAngle( -GetAngle() );
362  //Fall through
363  default:
364  case S_CURVE:
365  case S_SEGMENT:
366  if( aMirrorAroundXAxis )
367  {
368  MIRROR( m_Start0.y, aCentre.y );
369  MIRROR( m_End0.y, aCentre.y );
370  MIRROR( m_Bezier0_C1.y, aCentre.y );
371  MIRROR( m_Bezier0_C2.y, aCentre.y );
372  }
373  else
374  {
375  MIRROR( m_Start0.x, aCentre.x );
376  MIRROR( m_End0.x, aCentre.x );
377  MIRROR( m_Bezier0_C1.x, aCentre.x );
378  MIRROR( m_Bezier0_C2.x, aCentre.x );
379  }
380 
381  for( unsigned ii = 0; ii < m_BezierPoints.size(); ii++ )
382  {
383  if( aMirrorAroundXAxis )
384  MIRROR( m_BezierPoints[ii].y, aCentre.y );
385  else
386  MIRROR( m_BezierPoints[ii].x, aCentre.x );
387  }
388 
389  break;
390 
391  case S_POLYGON:
392  // polygon corners coordinates are always relative to the
393  // footprint position, orientation 0
394  for( auto iter = m_Poly.Iterate(); iter; iter++ )
395  {
396  if( aMirrorAroundXAxis )
397  MIRROR( iter->y, aCentre.y );
398  else
399  MIRROR( iter->x, aCentre.x );
400  }
401  }
402 
403  SetDrawCoord();
404 }
405 
406 void EDGE_MODULE::Rotate( const wxPoint& aRotCentre, double aAngle )
407 {
408  // We should rotate the relative coordinates, but to avoid duplicate code,
409  // do the base class rotation of draw coordinates, which is acceptable
410  // because in module editor, m_Pos0 = m_Pos
411  DRAWSEGMENT::Rotate( aRotCentre, aAngle );
412 
413  // and now update the relative coordinates, which are
414  // the reference in most transforms.
415  SetLocalCoord();
416 }
417 
418 
419 void EDGE_MODULE::Move( const wxPoint& aMoveVector )
420 {
421  // Move an edge of the footprint.
422  // This is a footprint shape modification.
423  m_Start0 += aMoveVector;
424  m_End0 += aMoveVector;
425  m_Bezier0_C1 += aMoveVector;
426  m_Bezier0_C2 += aMoveVector;
427 
428  switch( GetShape() )
429  {
430  default:
431  break;
432 
433  case S_POLYGON:
434  // polygon corners coordinates are always relative to the
435  // footprint position, orientation 0
436  for( auto iter = m_Poly.Iterate(); iter; iter++ )
437  *iter += VECTOR2I( aMoveVector );
438 
439  break;
440  }
441 
442  SetDrawCoord();
443 }
444 
445 unsigned int EDGE_MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
446 {
447  const int HIDE = std::numeric_limits<unsigned int>::max();
448 
449  if( !aView )
450  return 0;
451 
452  // Handle Render tab switches
453  if( !IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
454  return HIDE;
455 
456  if( IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
457  return HIDE;
458 
459  // Other layers are shown without any conditions
460  return 0;
461 }
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:202
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.
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:206
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:416
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:160
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:197
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
EDA_UNITS_T
Definition: common.h:133
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:114
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible() Returns information about visibility of a particular layer.
Definition: view.h:416
std::vector< wxPoint > m_BezierPoints