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 #include <math/util.h> // for KiROUND
46 #include <pgm_base.h>
49 
50 #include <pcb_edit_frame.h>
51 #include <class_board.h>
52 #include <class_module.h>
53 #include <class_edge_mod.h>
54 
55 #include <view/view.h>
56 
57 #include <cstdio>
58 
61 {
62  m_Shape = aShape;
63  m_Angle = 0;
64  m_Layer = F_SilkS;
65 }
66 
67 
69 {
70 }
71 
72 
74 {
75  MODULE* module = (MODULE*) m_Parent;
76 
77  if( module == NULL )
78  {
79  m_Start0 = m_Start;
80  m_End0 = m_End;
83  return;
84  }
85 
86  m_Start0 = m_Start - module->GetPosition();
87  m_End0 = m_End - module->GetPosition();
88  m_Bezier0_C1 = m_BezierC1 - module->GetPosition();
89  m_Bezier0_C2 = m_BezierC2 - module->GetPosition();
90  double angle = module->GetOrientation();
92  RotatePoint( &m_End0.x, &m_End0.y, -angle );
95 }
96 
97 
99 {
100  MODULE* module = (MODULE*) m_Parent;
101 
102  m_Start = m_Start0;
103  m_End = m_End0;
106 
107  if( module )
108  {
109  RotatePoint( &m_Start.x, &m_Start.y, module->GetOrientation() );
110  RotatePoint( &m_End.x, &m_End.y, module->GetOrientation() );
113 
114  m_Start += module->GetPosition();
115  m_End += module->GetPosition();
116  m_BezierC1 += module->GetPosition();
117  m_BezierC2 += module->GetPosition();
118  }
119 
121 }
122 
123 
124 void EDGE_MODULE::Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& offset )
125 {
126  int ux0, uy0, dx, dy, radius, StAngle, EndAngle;
127  MODULE* module = (MODULE*) m_Parent;
128  BOARD* brd = GetBoard( );
129 
130  if( !module || !brd->IsLayerVisible( m_Layer ) )
131  return;
132 
133  COLOR4D color = Pgm().GetSettingsManager().GetColorSettings()->GetColor( m_Layer );
134  auto displ_opts = aFrame->GetDisplayOptions();
135 
136  ux0 = m_Start.x - offset.x;
137  uy0 = m_Start.y - offset.y;
138 
139  dx = m_End.x - offset.x;
140  dy = m_End.y - offset.y;
141 
142  bool filled = displ_opts.m_DisplayModEdgeFill;
143 
144  if( IsCopperLayer( m_Layer ) )
145  filled = displ_opts.m_DisplayPcbTrackFill;
146 
147  switch( m_Shape )
148  {
149  case S_SEGMENT:
150  if( filled )
151  GRLine( nullptr, DC, ux0, uy0, dx, dy, m_Width, color );
152  else
153  // SKETCH Mode
154  GRCSegm( nullptr, DC, ux0, uy0, dx, dy, m_Width, color );
155 
156  break;
157 
158  case S_CIRCLE:
159  radius = KiROUND( Distance( ux0, uy0, dx, dy ) );
160 
161  if( filled )
162  {
163  GRCircle( nullptr, DC, ux0, uy0, radius, m_Width, color );
164  }
165  else // SKETCH Mode
166  {
167  GRCircle( nullptr, DC, ux0, uy0, radius + (m_Width / 2), color );
168  GRCircle( nullptr, DC, ux0, uy0, radius - (m_Width / 2), color );
169  }
170 
171  break;
172 
173  case S_ARC:
174  radius = KiROUND( Distance( ux0, uy0, dx, dy ) );
175  StAngle = ArcTangente( dy - uy0, dx - ux0 );
176  EndAngle = StAngle + m_Angle;
177 
178  if( StAngle > EndAngle )
179  std::swap( StAngle, EndAngle );
180 
181  if( filled )
182  {
183  GRArc( nullptr, DC, ux0, uy0, StAngle, EndAngle, radius, m_Width, color );
184  }
185  else // SKETCH Mode
186  {
187  GRArc( nullptr, DC, ux0, uy0, StAngle, EndAngle, radius + (m_Width / 2), color );
188  GRArc( nullptr, DC, ux0, uy0, StAngle, EndAngle, radius - (m_Width / 2), color );
189  }
190  break;
191 
192  case S_POLYGON:
193  if( m_Poly.IsEmpty() )
194  break;
195 
196  {
197  // We must compute absolute coordinates from m_PolyPoints
198  // which are relative to module position, orientation 0
199  std::vector<wxPoint> points;
200 
201  for( auto iter = m_Poly.CIterate(); iter; iter++ )
202  {
203  points.emplace_back( iter->x,iter->y );
204  }
205 
206  for( unsigned ii = 0; ii < points.size(); ii++ )
207  {
208  wxPoint& pt = points[ii];
209 
210  RotatePoint( &pt.x, &pt.y, module->GetOrientation() );
211  pt += module->GetPosition() - offset;
212  }
213 
214  GRPoly( nullptr, DC, points.size(), &points[0], true, m_Width, color, color );
215  }
216  break;
217 
218  case S_CURVE:
219  {
221 
222  wxPoint& startp = m_BezierPoints[0];
223 
224  for( unsigned int i = 1; i < m_BezierPoints.size(); i++ )
225  {
226  wxPoint& endp = m_BezierPoints[i];
227 
228  if( filled )
229  GRFilledSegment( nullptr, DC, startp-offset, endp-offset, m_Width, color );
230  else
231  GRCSegm( nullptr, DC, startp-offset, endp-offset, m_Width, color );
232 
233  startp = m_BezierPoints[i];
234  }
235  }
236  break;
237 
238  default:
239  break;
240  }
241 }
242 
243 
244 // see class_edge_mod.h
245 void EDGE_MODULE::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
246 {
247  wxString msg;
248 
249  MODULE* module = (MODULE*) m_Parent;
250 
251  if( !module )
252  return;
253 
254  BOARD* board = (BOARD*) module->GetParent();
255 
256  if( !board )
257  return;
258 
259  aList.emplace_back( _( "Footprint" ), module->GetReference(), DARKCYAN );
260 
261  // append the features shared with the base class
262  DRAWSEGMENT::GetMsgPanelInfo( aUnits, aList );
263 }
264 
265 
267 {
268  return wxString::Format( _( "Graphic %s of %s on %s" ),
269  ShowShape( m_Shape ),
270  ((MODULE*) GetParent())->GetReference(),
271  GetLayerName() );
272 }
273 
274 
276 {
277  return show_mod_edge_xpm;
278 }
279 
280 
282 {
283  return new EDGE_MODULE( *this );
284 }
285 
286 
287 void EDGE_MODULE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
288 {
289  wxPoint pt( 0, 0 );
290 
291  switch( GetShape() )
292  {
293  case S_ARC:
294  SetAngle( -GetAngle() );
295  //Fall through
296  default:
297  case S_SEGMENT:
298  case S_CURVE:
299  // If Start0 and Start are equal (ie: ModEdit), then flip both sets around the
300  // centre point.
301  if( m_Start == m_Start0 )
302  pt = aCentre;
303 
304  if( aFlipLeftRight )
305  {
306  MIRROR( m_Start.x, aCentre.x );
307  MIRROR( m_End.x, aCentre.x );
308  MIRROR( m_BezierC1.x, aCentre.x );
309  MIRROR( m_BezierC2.x, aCentre.x );
310  MIRROR( m_Start0.x, pt.x );
311  MIRROR( m_End0.x, pt.x );
312  MIRROR( m_Bezier0_C1.x, pt.x );
313  MIRROR( m_Bezier0_C2.x, pt.x );
314  }
315  else
316  {
317  MIRROR( m_Start.y, aCentre.y );
318  MIRROR( m_End.y, aCentre.y );
319  MIRROR( m_BezierC1.y, aCentre.y );
320  MIRROR( m_BezierC2.y, aCentre.y );
321  MIRROR( m_Start0.y, pt.y );
322  MIRROR( m_End0.y, pt.y );
323  MIRROR( m_Bezier0_C1.y, pt.y );
324  MIRROR( m_Bezier0_C2.y, pt.y );
325  }
326 
328  break;
329 
330  case S_POLYGON:
331  // polygon corners coordinates are always relative to the
332  // footprint position, orientation 0
333  m_Poly.Mirror( aFlipLeftRight, !aFlipLeftRight );
334  break;
335  }
336 
337  // DRAWSEGMENT items are not usually on copper layers, but
338  // it can happen in microwave apps.
339  // However, currently, only on Front or Back layers.
340  // So the copper layers count is not taken in account
341  SetLayer( FlipLayer( GetLayer() ) );
342 }
343 
345 {
346  if( GetParent() && GetParent()->GetLayer() == B_Cu )
347  return true;
348  return false;
349 }
350 
351 void EDGE_MODULE::Mirror( wxPoint aCentre, bool aMirrorAroundXAxis )
352 {
353  // Mirror an edge of the footprint. the layer is not modified
354  // This is a footprint shape modification.
355  switch( GetShape() )
356  {
357  case S_ARC:
358  SetAngle( -GetAngle() );
359  //Fall through
360  default:
361  case S_CURVE:
362  case S_SEGMENT:
363  if( aMirrorAroundXAxis )
364  {
365  MIRROR( m_Start0.y, aCentre.y );
366  MIRROR( m_End0.y, aCentre.y );
367  MIRROR( m_Bezier0_C1.y, aCentre.y );
368  MIRROR( m_Bezier0_C2.y, aCentre.y );
369  }
370  else
371  {
372  MIRROR( m_Start0.x, aCentre.x );
373  MIRROR( m_End0.x, aCentre.x );
374  MIRROR( m_Bezier0_C1.x, aCentre.x );
375  MIRROR( m_Bezier0_C2.x, aCentre.x );
376  }
377 
378  for( unsigned ii = 0; ii < m_BezierPoints.size(); ii++ )
379  {
380  if( aMirrorAroundXAxis )
381  MIRROR( m_BezierPoints[ii].y, aCentre.y );
382  else
383  MIRROR( m_BezierPoints[ii].x, aCentre.x );
384  }
385 
386  break;
387 
388  case S_POLYGON:
389  // polygon corners coordinates are always relative to the
390  // footprint position, orientation 0
391  m_Poly.Mirror( !aMirrorAroundXAxis, aMirrorAroundXAxis );
392  break;
393  }
394 
395  SetDrawCoord();
396 }
397 
398 void EDGE_MODULE::Rotate( const wxPoint& aRotCentre, double aAngle )
399 {
400  // We should rotate the relative coordinates, but to avoid duplicate code,
401  // do the base class rotation of draw coordinates, which is acceptable
402  // because in module editor, m_Pos0 = m_Pos
403  DRAWSEGMENT::Rotate( aRotCentre, aAngle );
404 
405  // and now update the relative coordinates, which are
406  // the reference in most transforms.
407  SetLocalCoord();
408 }
409 
410 
411 void EDGE_MODULE::Move( const wxPoint& aMoveVector )
412 {
413  // Move an edge of the footprint.
414  // This is a footprint shape modification.
415  m_Start0 += aMoveVector;
416  m_End0 += aMoveVector;
417  m_Bezier0_C1 += aMoveVector;
418  m_Bezier0_C2 += aMoveVector;
419 
420  switch( GetShape() )
421  {
422  default:
423  break;
424 
425  case S_POLYGON:
426  // polygon corners coordinates are always relative to the
427  // footprint position, orientation 0
428  m_Poly.Move( VECTOR2I( aMoveVector ) );
429 
430  break;
431  }
432 
433  SetDrawCoord();
434 }
435 
436 unsigned int EDGE_MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
437 {
438  const int HIDE = std::numeric_limits<unsigned int>::max();
439 
440  if( !aView )
441  return 0;
442 
443  // Handle Render tab switches
444  if( !IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
445  return HIDE;
446 
447  if( IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
448  return HIDE;
449 
450  // Other layers are shown without any conditions
451  return 0;
452 }
EDA_UNITS
Definition: common.h:184
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:215
EDA_ITEM * m_Parent
Linked list: Link (parent struct)
Definition: base_struct.h:183
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:103
PNG memory record (file in memory).
Definition: bitmap_def.h:29
virtual unsigned int ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
void GetMsgPanelInfo(EDA_UNITS aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
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
void GRPoly(EDA_RECT *ClipBox, wxDC *DC, int n, const wxPoint *Points, bool Fill, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:542
SHAPE_POLY_SET m_Poly
Stores the S_POLYGON shape.
int color
Definition: DXF_plotter.cpp:61
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:485
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
double m_Angle
Used only for Arcs: Arc angle in 1/10 deg.
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Function GetDisplayOptions returns the display options current in use Display options are relative to...
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirrors the line points about y or x (or both)
wxPoint m_End0
End point, relative to module origin, orient 0.
This file contains miscellaneous commonly used macros and functions.
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
wxPoint m_BezierC1
Bezier Control Point 1.
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:436
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
void Mirror(const wxPoint aCentre, bool aMirrorAroundXAxis)
Mirror an edge of the footprint.
wxPoint m_Start
Line start point or Circle and Arc center.
#define NULL
void Move(const VECTOR2I &aVector) override
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.
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:749
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.
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
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
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.
void GetMsgPanelInfo(EDA_UNITS aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
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:431
virtual void Rotate(const wxPoint &aRotCentre, double aAngle) override
Function Rotate Rotate this object.
see class PGM_BASE
const BITMAP_OPAQUE show_mod_edge_xpm[1]
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
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:163
#define _(s)
Definition: 3d_actions.cpp:33
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:596
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.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:61
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:166
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Flip entity relative to aCentre.
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.
int m_Width
thickness of lines ...
Module description (excepted pads)
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:162
wxPoint m_Start0
Start point or center, relative to module origin, orient 0.
VIEW.
Definition: view.h:61
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:210
PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible() Returns information about visibility of a particular layer.
Definition: view.h:416
std::vector< wxPoint > m_BezierPoints
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:40