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 
47 #include <pcb_edit_frame.h>
48 #include <class_board.h>
49 #include <class_module.h>
50 #include <class_edge_mod.h>
51 
52 #include <view/view.h>
53 
54 #include <cstdio>
55 
58 {
59  m_Shape = aShape;
60  m_Angle = 0;
61  m_Layer = F_SilkS;
62 }
63 
64 
66 {
67 }
68 
69 
71 {
72  MODULE* module = (MODULE*) m_Parent;
73 
74  if( module == NULL )
75  {
76  m_Start0 = m_Start;
77  m_End0 = m_End;
80  return;
81  }
82 
83  m_Start0 = m_Start - module->GetPosition();
84  m_End0 = m_End - module->GetPosition();
85  m_Bezier0_C1 = m_BezierC1 - module->GetPosition();
86  m_Bezier0_C2 = m_BezierC2 - module->GetPosition();
87  double angle = module->GetOrientation();
89  RotatePoint( &m_End0.x, &m_End0.y, -angle );
92 }
93 
94 
96 {
97  MODULE* module = (MODULE*) m_Parent;
98 
99  m_Start = m_Start0;
100  m_End = m_End0;
103 
104  if( module )
105  {
106  RotatePoint( &m_Start.x, &m_Start.y, module->GetOrientation() );
107  RotatePoint( &m_End.x, &m_End.y, module->GetOrientation() );
110 
111  m_Start += module->GetPosition();
112  m_End += module->GetPosition();
113  m_BezierC1 += module->GetPosition();
114  m_BezierC2 += module->GetPosition();
115  }
116 
118 }
119 
120 
121 void EDGE_MODULE::Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& offset )
122 {
123  int ux0, uy0, dx, dy, radius, StAngle, EndAngle;
124  MODULE* module = (MODULE*) m_Parent;
125  BOARD* brd = GetBoard( );
126 
127  if( !module || !brd->IsLayerVisible( m_Layer ) )
128  return;
129 
130  auto color = aFrame->Settings().Colors().GetLayerColor( m_Layer );
131  auto displ_opts = aFrame->GetDisplayOptions();
132 
133  ux0 = m_Start.x - offset.x;
134  uy0 = m_Start.y - offset.y;
135 
136  dx = m_End.x - offset.x;
137  dy = m_End.y - offset.y;
138 
139  bool filled = displ_opts.m_DisplayModEdgeFill;
140 
141  if( IsCopperLayer( m_Layer ) )
142  filled = displ_opts.m_DisplayPcbTrackFill;
143 
144  switch( m_Shape )
145  {
146  case S_SEGMENT:
147  if( filled )
148  GRLine( nullptr, DC, ux0, uy0, dx, dy, m_Width, color );
149  else
150  // SKETCH Mode
151  GRCSegm( nullptr, DC, ux0, uy0, dx, dy, m_Width, color );
152 
153  break;
154 
155  case S_CIRCLE:
156  radius = KiROUND( Distance( ux0, uy0, dx, dy ) );
157 
158  if( filled )
159  {
160  GRCircle( nullptr, DC, ux0, uy0, radius, m_Width, color );
161  }
162  else // SKETCH Mode
163  {
164  GRCircle( nullptr, DC, ux0, uy0, radius + (m_Width / 2), color );
165  GRCircle( nullptr, DC, ux0, uy0, radius - (m_Width / 2), color );
166  }
167 
168  break;
169 
170  case S_ARC:
171  radius = KiROUND( Distance( ux0, uy0, dx, dy ) );
172  StAngle = ArcTangente( dy - uy0, dx - ux0 );
173  EndAngle = StAngle + m_Angle;
174 
175  if( StAngle > EndAngle )
176  std::swap( StAngle, EndAngle );
177 
178  if( filled )
179  {
180  GRArc( nullptr, DC, ux0, uy0, StAngle, EndAngle, radius, m_Width, color );
181  }
182  else // SKETCH Mode
183  {
184  GRArc( nullptr, DC, ux0, uy0, StAngle, EndAngle, radius + (m_Width / 2), color );
185  GRArc( nullptr, DC, ux0, uy0, StAngle, EndAngle, radius - (m_Width / 2), color );
186  }
187  break;
188 
189  case S_POLYGON:
190  if( m_Poly.IsEmpty() )
191  break;
192 
193  {
194  // We must compute absolute coordinates from m_PolyPoints
195  // which are relative to module position, orientation 0
196  std::vector<wxPoint> points;
197 
198  for( auto iter = m_Poly.CIterate(); iter; iter++ )
199  {
200  points.emplace_back( iter->x,iter->y );
201  }
202 
203  for( unsigned ii = 0; ii < points.size(); ii++ )
204  {
205  wxPoint& pt = points[ii];
206 
207  RotatePoint( &pt.x, &pt.y, module->GetOrientation() );
208  pt += module->GetPosition() - offset;
209  }
210 
211  GRPoly( nullptr, DC, points.size(), &points[0], true, m_Width, color, color );
212  }
213  break;
214 
215  case S_CURVE:
216  {
218 
219  wxPoint& startp = m_BezierPoints[0];
220 
221  for( unsigned int i = 1; i < m_BezierPoints.size(); i++ )
222  {
223  wxPoint& endp = m_BezierPoints[i];
224 
225  if( filled )
226  GRFilledSegment( nullptr, DC, startp-offset, endp-offset, m_Width, color );
227  else
228  GRCSegm( nullptr, DC, startp-offset, endp-offset, m_Width, color );
229 
230  startp = m_BezierPoints[i];
231  }
232  }
233  break;
234 
235  default:
236  break;
237  }
238 }
239 
240 
241 // see class_edge_mod.h
242 void EDGE_MODULE::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
243 {
244  wxString msg;
245 
246  MODULE* module = (MODULE*) m_Parent;
247 
248  if( !module )
249  return;
250 
251  BOARD* board = (BOARD*) module->GetParent();
252 
253  if( !board )
254  return;
255 
256  aList.emplace_back( _( "Footprint" ), module->GetReference(), DARKCYAN );
257 
258  // append the features shared with the base class
259  DRAWSEGMENT::GetMsgPanelInfo( aUnits, aList );
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 
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  m_Poly.Mirror( aFlipLeftRight, !aFlipLeftRight );
331  break;
332  }
333 
334  // DRAWSEGMENT items are not usually on copper layers, but
335  // it can happen in microwave apps.
336  // However, currently, only on Front or Back layers.
337  // So the copper layers count is not taken in account
338  SetLayer( FlipLayer( GetLayer() ) );
339 }
340 
342 {
343  if( GetParent() && GetParent()->GetLayer() == B_Cu )
344  return true;
345  return false;
346 }
347 
348 void EDGE_MODULE::Mirror( wxPoint aCentre, bool aMirrorAroundXAxis )
349 {
350  // Mirror an edge of the footprint. the layer is not modified
351  // This is a footprint shape modification.
352  switch( GetShape() )
353  {
354  case S_ARC:
355  SetAngle( -GetAngle() );
356  //Fall through
357  default:
358  case S_CURVE:
359  case S_SEGMENT:
360  if( aMirrorAroundXAxis )
361  {
362  MIRROR( m_Start0.y, aCentre.y );
363  MIRROR( m_End0.y, aCentre.y );
364  MIRROR( m_Bezier0_C1.y, aCentre.y );
365  MIRROR( m_Bezier0_C2.y, aCentre.y );
366  }
367  else
368  {
369  MIRROR( m_Start0.x, aCentre.x );
370  MIRROR( m_End0.x, aCentre.x );
371  MIRROR( m_Bezier0_C1.x, aCentre.x );
372  MIRROR( m_Bezier0_C2.x, aCentre.x );
373  }
374 
375  for( unsigned ii = 0; ii < m_BezierPoints.size(); ii++ )
376  {
377  if( aMirrorAroundXAxis )
378  MIRROR( m_BezierPoints[ii].y, aCentre.y );
379  else
380  MIRROR( m_BezierPoints[ii].x, aCentre.x );
381  }
382 
383  break;
384 
385  case S_POLYGON:
386  // polygon corners coordinates are always relative to the
387  // footprint position, orientation 0
388  m_Poly.Mirror( !aMirrorAroundXAxis, aMirrorAroundXAxis );
389  break;
390  }
391 
392  SetDrawCoord();
393 }
394 
395 void EDGE_MODULE::Rotate( const wxPoint& aRotCentre, double aAngle )
396 {
397  // We should rotate the relative coordinates, but to avoid duplicate code,
398  // do the base class rotation of draw coordinates, which is acceptable
399  // because in module editor, m_Pos0 = m_Pos
400  DRAWSEGMENT::Rotate( aRotCentre, aAngle );
401 
402  // and now update the relative coordinates, which are
403  // the reference in most transforms.
404  SetLocalCoord();
405 }
406 
407 
408 void EDGE_MODULE::Move( const wxPoint& aMoveVector )
409 {
410  // Move an edge of the footprint.
411  // This is a footprint shape modification.
412  m_Start0 += aMoveVector;
413  m_End0 += aMoveVector;
414  m_Bezier0_C1 += aMoveVector;
415  m_Bezier0_C2 += aMoveVector;
416 
417  switch( GetShape() )
418  {
419  default:
420  break;
421 
422  case S_POLYGON:
423  // polygon corners coordinates are always relative to the
424  // footprint position, orientation 0
425  m_Poly.Move( VECTOR2I( aMoveVector ) );
426 
427  break;
428  }
429 
430  SetDrawCoord();
431 }
432 
433 unsigned int EDGE_MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
434 {
435  const int HIDE = std::numeric_limits<unsigned int>::max();
436 
437  if( !aView )
438  return 0;
439 
440  // Handle Render tab switches
441  if( !IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
442  return HIDE;
443 
444  if( IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
445  return HIDE;
446 
447  // Other layers are shown without any conditions
448  return 0;
449 }
EDA_UNITS
Definition: common.h:72
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:177
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
COLOR4D GetLayerColor(LAYER_NUM aLayer) const
Function GetLayerColor.
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.
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: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
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.
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:449
virtual void Rotate(const wxPoint &aRotCentre, double aAngle) override
Function Rotate Rotate this object.
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:160
#define _(s)
Definition: 3d_actions.cpp:31
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:163
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