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 <wxstruct.h>
35 #include <trigo.h>
36 #include <class_drawpanel.h>
37 #include <class_pcb_screen.h>
38 #include <confirm.h>
39 #include <kicad_string.h>
40 #include <richio.h>
41 #include <macros.h>
42 #include <math_for_graphics.h>
43 #include <wxBasePcbFrame.h>
44 #include <msgpanel.h>
45 #include <base_units.h>
46 #include <bitmaps.h>
47 
48 #include <wxPcbStruct.h>
49 #include <class_board.h>
50 #include <class_module.h>
51 #include <class_edge_mod.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;
77  return;
78  }
79 
80  m_Start0 = m_Start - module->GetPosition();
81  m_End0 = m_End - module->GetPosition();
82  double angle = module->GetOrientation();
83  RotatePoint( &m_Start0.x, &m_Start0.y, -angle );
84  RotatePoint( &m_End0.x, &m_End0.y, -angle );
85 }
86 
87 
89 {
90  MODULE* module = (MODULE*) m_Parent;
91 
92  m_Start = m_Start0;
93  m_End = m_End0;
94 
95  if( module )
96  {
97  RotatePoint( &m_Start.x, &m_Start.y, module->GetOrientation() );
98  RotatePoint( &m_End.x, &m_End.y, module->GetOrientation() );
99 
100  m_Start += module->GetPosition();
101  m_End += module->GetPosition();
102  }
103 }
104 
105 
106 void EDGE_MODULE::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE draw_mode,
107  const wxPoint& offset )
108 {
109  int ux0, uy0, dx, dy, radius, StAngle, EndAngle;
110  PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
111 
112  MODULE* module = (MODULE*) m_Parent;
113 
114  if( !module )
115  return;
116 
117  BOARD* brd = GetBoard( );
118 
119  if( brd->IsLayerVisible( m_Layer ) == false )
120  return;
121 
122 
123  auto frame = static_cast<PCB_BASE_FRAME*> ( panel->GetParent() );
124  auto color = frame->Settings().Colors().GetLayerColor( m_Layer );
125 
126  auto displ_opts = (PCB_DISPLAY_OPTIONS*)( panel->GetDisplayOptions() );
127 
128  if(( draw_mode & GR_ALLOW_HIGHCONTRAST ) && displ_opts && displ_opts->m_ContrastModeDisplay )
129  {
130  if( !IsOnLayer( curr_layer ) )
132  }
133 
134  ux0 = m_Start.x - offset.x;
135  uy0 = m_Start.y - offset.y;
136 
137  dx = m_End.x - offset.x;
138  dy = m_End.y - offset.y;
139 
140  GRSetDrawMode( DC, draw_mode );
141  bool filled = displ_opts ? displ_opts->m_DisplayModEdgeFill : FILLED;
142 
143  if( IsCopperLayer( m_Layer ) )
144  filled = displ_opts ? displ_opts->m_DisplayPcbTrackFill : FILLED;
145 
146  switch( m_Shape )
147  {
148  case S_SEGMENT:
149  if( filled )
150  GRLine( panel->GetClipBox(), DC, ux0, uy0, dx, dy, m_Width, color );
151  else
152  // SKETCH Mode
153  GRCSegm( panel->GetClipBox(), DC, ux0, uy0, dx, dy, m_Width, color );
154 
155  break;
156 
157  case S_CIRCLE:
158  radius = KiROUND( Distance( ux0, uy0, dx, dy ) );
159 
160  if( filled )
161  {
162  GRCircle( panel->GetClipBox(), DC, ux0, uy0, radius, m_Width, color );
163  }
164  else // SKETCH Mode
165  {
166  GRCircle( panel->GetClipBox(), DC, ux0, uy0, radius + (m_Width / 2), color );
167  GRCircle( panel->GetClipBox(), DC, ux0, uy0, radius - (m_Width / 2), color );
168  }
169 
170  break;
171 
172  case S_ARC:
173  radius = KiROUND( Distance( ux0, uy0, dx, dy ) );
174  StAngle = ArcTangente( dy - uy0, dx - ux0 );
175  EndAngle = StAngle + m_Angle;
176 
177  if( !panel->GetPrintMirrored() )
178  {
179  if( StAngle > EndAngle )
180  std::swap( StAngle, EndAngle );
181  }
182  else // Mirrored mode: arc orientation is reversed
183  {
184  if( StAngle < EndAngle )
185  std::swap( StAngle, EndAngle );
186  }
187 
188  if( filled )
189  {
190  GRArc( panel->GetClipBox(), DC, ux0, uy0, StAngle, EndAngle, radius, m_Width, color );
191  }
192  else // SKETCH Mode
193  {
194  GRArc( panel->GetClipBox(), DC, ux0, uy0, StAngle, EndAngle,
195  radius + (m_Width / 2), color );
196  GRArc( panel->GetClipBox(), DC, ux0, uy0, StAngle, EndAngle,
197  radius - (m_Width / 2), color );
198  }
199  break;
200 
201  case S_POLYGON:
202  if( m_Poly.IsEmpty() )
203  break;
204 
205  {
206  // We must compute absolute coordinates from m_PolyPoints
207  // which are relative to module position, orientation 0
208  std::vector<wxPoint> points;
209 
210  for( auto iter = m_Poly.CIterate(); iter; iter++ )
211  {
212  points.push_back( wxPoint( iter->x,iter->y ) );
213  }
214 
215  for( unsigned ii = 0; ii < points.size(); ii++ )
216  {
217  wxPoint& pt = points[ii];
218 
219  RotatePoint( &pt.x, &pt.y, module->GetOrientation() );
220  pt += module->GetPosition() - offset;
221  }
222 
223  GRPoly( panel->GetClipBox(), DC, points.size(), &points[0], true, m_Width, color, color );
224  }
225  break;
226 
227  default:
228  break;
229  }
230 }
231 
232 
233 // see class_edge_mod.h
234 void EDGE_MODULE::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
235 {
236  wxString msg;
237 
238  MODULE* module = (MODULE*) m_Parent;
239 
240  if( !module )
241  return;
242 
243  BOARD* board = (BOARD*) module->GetParent();
244 
245  if( !board )
246  return;
247 
248  aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), module->GetReference(), DARKCYAN ) );
249  aList.push_back( MSG_PANEL_ITEM( _( "Value" ), module->GetValue(), BLUE ) );
250  msg.Printf( wxT( "%8.8lX" ), module->GetTimeStamp() );
251  aList.push_back( MSG_PANEL_ITEM( _( "TimeStamp" ), msg, BROWN ) );
252  aList.push_back( MSG_PANEL_ITEM( _( "Footprint Layer" ),
253  module->GetLayerName(), RED ) );
254 
255  // append the features shared with the base class
257 }
258 
259 
260 
262 {
263  wxString text;
264  text.Printf( _( "Graphic (%s) on %s of %s" ),
265  GetChars( ShowShape( m_Shape ) ),
266  GetChars( GetLayerName() ),
267  GetChars( ((MODULE*) GetParent())->GetReference() ) );
268 
269  return text;
270 }
271 
272 
274 {
275  return show_mod_edge_xpm;
276 }
277 
278 
280 {
281  return new EDGE_MODULE( *this );
282 }
283 
284 
285 void EDGE_MODULE::Flip( const wxPoint& aCentre )
286 {
287  wxPoint pt;
288 
289  switch( GetShape() )
290  {
291  case S_ARC:
292  SetAngle( -GetAngle() );
293  //Fall through
294  default:
295  case S_SEGMENT:
296  pt = GetStart();
297  MIRROR( pt.y, aCentre.y );
298  SetStart( pt );
299 
300  pt = GetEnd();
301  MIRROR( pt.y, aCentre.y );
302  SetEnd( pt );
303 
304  MIRROR( m_Start0.y, 0 );
305  MIRROR( m_End0.y, 0 );
306  break;
307 
308  case S_POLYGON:
309  // polygon corners coordinates are always relative to the
310  // footprint position, orientation 0
311  for( auto iter = m_Poly.Iterate(); iter; iter++ )
312  {
313  MIRROR( iter->y, 0 );
314  }
315  break;
316  }
317 
318  // DRAWSEGMENT items are not usually on copper layers, but
319  // it can happen in microwave apps.
320  // However, currently, only on Front or Back layers.
321  // So the copper layers count is not taken in account
322  SetLayer( FlipLayer( GetLayer() ) );
323 }
324 
325 
326 void EDGE_MODULE::Mirror( wxPoint aCentre, bool aMirrorAroundXAxis )
327 {
328  // Mirror an edge of the footprint. the layer is not modified
329  // This is a footprint shape modification.
330  switch( GetShape() )
331  {
332  case S_ARC:
333  SetAngle( -GetAngle() );
334  //Fall through
335  default:
336  case S_SEGMENT:
337  if( aMirrorAroundXAxis )
338  {
339  MIRROR( m_Start0.y, aCentre.y );
340  MIRROR( m_End0.y, aCentre.y );
341  }
342  else
343  {
344  MIRROR( m_Start0.x, aCentre.x );
345  MIRROR( m_End0.x, aCentre.x );
346  }
347  break;
348 
349  case S_POLYGON:
350  // polygon corners coordinates are always relative to the
351  // footprint position, orientation 0
352  for( auto iter = m_Poly.Iterate(); iter; iter++ )
353  {
354  if( aMirrorAroundXAxis )
355  MIRROR( iter->y, aCentre.y );
356  else
357  MIRROR( iter->x, aCentre.x );
358  }
359  }
360 
361  SetDrawCoord();
362 }
363 
364 void EDGE_MODULE::Rotate( const wxPoint& aRotCentre, double aAngle )
365 {
366  // We should rotate the relative coordinates, but to avoid duplicate code,
367  // do the base class rotation of draw coordinates, which is acceptable
368  // because in module editor, m_Pos0 = m_Pos
369  DRAWSEGMENT::Rotate( aRotCentre, aAngle );
370 
371  // and now update the relative coordinates, which are
372  // the reference in most transforms.
373  SetLocalCoord();
374 }
375 
376 
377 void EDGE_MODULE::Move( const wxPoint& aMoveVector )
378 {
379  // Move an edge of the footprint.
380  // This is a footprint shape modification.
381  m_Start0 += aMoveVector;
382  m_End0 += aMoveVector;
383 
384  switch( GetShape() )
385  {
386  default:
387  break;
388 
389  case S_POLYGON:
390  // polygon corners coordinates are always relative to the
391  // footprint position, orientation 0
392  for( auto iter = m_Poly.Iterate(); iter; iter++ )
393  *iter += VECTOR2I( aMoveVector );
394  }
395 
396  SetDrawCoord();
397 }
void GetMsgPanelInfo(std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
Definition: colors.h:57
BOARD_ITEM_CONTAINER * GetParent() const
static wxString ShowShape(STROKE_T aShape)
Function ShowShape converts the enum STROKE_T integer value to a wxString.
void GRPoly(EDA_RECT *ClipBox, wxDC *DC, int n, wxPoint Points[], bool Fill, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:774
EDA_ITEM * m_Parent
Linked list: Link (parent struct)
Definition: base_struct.h:182
virtual void GetMsgPanelInfo(std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
PNG memory record (file in memory).
Definition: bitmap_types.h:38
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:296
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:106
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Function IsOnLayer tests to see if this object is on the given layer.
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.
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
Class BOARD to handle a board.
const wxPoint & GetPosition() const override
Definition: class_module.h:175
SHAPE_POLY_SET m_Poly
Stores the S_POLYGON shape.
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:445
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
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:488
const wxString & GetValue() const
Function GetValue.
Definition: class_module.h:467
usual segment : line with rounded ends
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
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:589
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
wxPoint m_End0
This file contains miscellaneous commonly used macros and functions.
void Rotate(const wxPoint &aRotCentre, double aAngle) override
Rotate an edge of the footprint.
PCB_LAYER_ID m_Layer
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:111
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...
PCB_LAYER_ID
A quick note on layer IDs:
STROKE_T GetShape() const
wxPoint m_Start
Line start point or Circle and Arc center.
Classes used in Pcbnew, CvPcb and GerbView.
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:271
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.
double GetOrientation() const
Definition: class_module.h:180
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:41
Base window classes and related definitions.
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:981
STROKE_T
Enum STROKE_T is the set of shapes for segments (graphic segments and tracks) which are often in the ...
EDA_RECT * GetClipBox()
STROKE_T m_Shape
Shape: line, Circle, Arc.
Definition: colors.h:60
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
EDA_DRAW_FRAME * GetParent() const
Definition: draw_panel.cpp:174
void Draw(EDA_DRAW_PANEL *panel, wxDC *DC, GR_DRAWMODE aDrawMode, const wxPoint &offset=ZeroOffset) override
Function Draw BOARD_ITEMs have their own color information.
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:358
void Flip(const wxPoint &aCentre) override
Flip entity relative to aCentre.
void SetStart(const wxPoint &aStart)
time_t GetTimeStamp() const
Definition: base_struct.h:218
void SetLocalCoord()
Set relative coordinates from draw coordinates.
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
virtual void Rotate(const wxPoint &aRotCentre, double aAngle) override
Function Rotate Rotate this object.
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
double GetAngle() const
bool GetPrintMirrored() const
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:439
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:828
EDGE_MODULE(MODULE *parent, STROKE_T aShape=S_SEGMENT)
void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:187
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:165
void SetEnd(const wxPoint &aEnd)
void SetAngle(double aAngle)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees...
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
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)
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
wxPoint m_Start0
void * GetDisplayOptions()
Function GetDisplayOptions A way to pass info to draw functions.
Definition: draw_panel.cpp:181
Class EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
double Distance(double x1, double y1, double x2, double y2)
EDGE_MODULE class definition.
Message panel definition file.
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer...
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:451
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
Definition: colors.h:62