KiCad PCB EDA Suite
microwave_polygon.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, jp.charras at wanadoo.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2015-2016 Wayne Stambaugh <stambaughw@verizon.net>
7  * Copyright (C) 1992-2020 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 
27 #include <confirm.h>
28 #include <trigo.h>
29 #include <kicad_string.h>
30 #include <gestfich.h>
31 #include <pcb_edit_frame.h>
32 #include <dialog_helpers.h>
33 #include <locale_io.h>
34 #include <richio.h>
35 #include <filter_reader.h>
36 #include <base_units.h>
37 #include <validators.h>
38 #include <dialog_text_entry.h>
39 #include <board.h>
40 #include <footprint.h>
41 #include <fp_shape.h>
43 #include <pcbnew.h>
44 #include <math/util.h> // for KiROUND
45 
46 static std::vector< wxRealPoint > PolyEdges;
47 static double ShapeScaleX, ShapeScaleY;
48 static wxSize ShapeSize;
49 static int PolyShapeType;
50 
51 
52 
53 /**************** Polygon Shapes ***********************/
54 
55 enum id_mw_cmd {
57 };
58 
59 
60 /* Setting polynomial form parameters
61  */
62 class MWAVE_POLYGONAL_SHAPE_DLG : public wxDialog
63 {
64 private:
66  wxRadioBox* m_ShapeOptionCtrl;
68 
69 public:
70  MWAVE_POLYGONAL_SHAPE_DLG( PCB_EDIT_FRAME* parent, const wxPoint& pos );
72 
73 private:
74  void OnOkClick( wxCommandEvent& event );
75  void OnCancelClick( wxCommandEvent& event );
76 
93  void ReadDataShapeDescr( wxCommandEvent& event );
94 
95  DECLARE_EVENT_TABLE()
96 };
97 
98 
99 BEGIN_EVENT_TABLE( MWAVE_POLYGONAL_SHAPE_DLG, wxDialog )
100  EVT_BUTTON( wxID_OK, MWAVE_POLYGONAL_SHAPE_DLG::OnOkClick )
101  EVT_BUTTON( wxID_CANCEL, MWAVE_POLYGONAL_SHAPE_DLG::OnCancelClick )
103 END_EVENT_TABLE()
104 
105 
107  const wxPoint& framepos ) :
108  wxDialog( parent, -1, _( "Complex shape" ), framepos, wxSize( 350, 280 ),
109  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
110 {
111  m_Parent = parent;
112 
113  PolyEdges.clear();
114 
115  wxBoxSizer* MainBoxSizer = new wxBoxSizer( wxHORIZONTAL );
116  SetSizer( MainBoxSizer );
117  wxBoxSizer* LeftBoxSizer = new wxBoxSizer( wxVERTICAL );
118  wxBoxSizer* RightBoxSizer = new wxBoxSizer( wxVERTICAL );
119  MainBoxSizer->Add( LeftBoxSizer, 0, wxGROW | wxALL, 5 );
120  MainBoxSizer->Add( RightBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
121 
122  wxButton* Button = new wxButton( this, wxID_OK, _( "OK" ) );
123  RightBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 );
124 
125  Button = new wxButton( this, wxID_CANCEL, _( "Cancel" ) );
126  RightBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 );
127 
128  Button = new wxButton( this, ID_READ_SHAPE_FILE,
129  _( "Read Shape Description File..." ) );
130  RightBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 );
131 
132  wxString shapelist[] = { _( "Normal" ), _( "Symmetrical" ), _( "Mirrored" ) };
133 
134  m_ShapeOptionCtrl = new wxRadioBox( this, -1, _( "Shape Option" ),
135  wxDefaultPosition, wxDefaultSize, 3,
136  shapelist, 1,
137  wxRA_SPECIFY_COLS );
138  LeftBoxSizer->Add( m_ShapeOptionCtrl, 0, wxGROW | wxALL, 5 );
139 
140  m_SizeCtrl = new EDA_SIZE_CTRL( this, _( "Size" ), ShapeSize, parent->GetUserUnits(),
141  LeftBoxSizer );
142 
143  GetSizer()->SetSizeHints( this );
144 }
145 
146 
147 void MWAVE_POLYGONAL_SHAPE_DLG::OnCancelClick( wxCommandEvent& event )
148 {
149  PolyEdges.clear();
150  EndModal( wxID_CANCEL );
151 }
152 
153 
154 void MWAVE_POLYGONAL_SHAPE_DLG::OnOkClick( wxCommandEvent& event )
155 {
157  PolyShapeType = m_ShapeOptionCtrl->GetSelection();
158  EndModal( wxID_OK );
159 }
160 
161 
163 {
164  static wxString lastpath; // To remember the last open path during a session
165  wxString fullFileName;
166  wxString mask = wxFileSelectorDefaultWildcardStr;
167 
168  fullFileName = EDA_FILE_SELECTOR( _( "Read descr shape file" ), lastpath,
169  fullFileName, wxEmptyString, mask, this,
170  wxFD_OPEN, true );
171 
172  if( fullFileName.IsEmpty() )
173  return;
174 
175  wxFileName fn( fullFileName );
176  lastpath = fn.GetPath();
177  PolyEdges.clear();
178 
179  FILE* File = wxFopen( fullFileName, wxT( "rt" ) );
180 
181  if( File == NULL )
182  {
183  DisplayError( this, _( "File not found" ) );
184  return;
185  }
186 
187  double unitconv = IU_PER_MM;
188  ShapeScaleX = ShapeScaleY = 1.0;
189 
190  FILE_LINE_READER fileReader( File, fullFileName );
191  FILTER_READER reader( fileReader );
192 
193  LOCALE_IO toggle;
194 
195  while( reader.ReadLine() )
196  {
197  char* Line = reader.Line();
198  char* param1 = strtok( Line, " =\n\r" );
199  char* param2 = strtok( NULL, " \t\n\r" );
200 
201  if( strncasecmp( param1, "Unit", 4 ) == 0 )
202  {
203  if( strncasecmp( param2, "inch", 4 ) == 0 )
204  unitconv = IU_PER_MILS*1000;
205 
206  if( strncasecmp( param2, "mm", 2 ) == 0 )
207  unitconv = IU_PER_MM;
208  }
209 
210  if( strncasecmp( param1, "$ENDCOORD", 8 ) == 0 )
211  break;
212 
213  if( strncasecmp( param1, "$COORD", 6 ) == 0 )
214  {
215  while( reader.ReadLine() )
216  {
217  Line = reader.Line();
218  param1 = strtok( Line, " \t\n\r" );
219  param2 = strtok( NULL, " \t\n\r" );
220 
221  if( strncasecmp( param1, "$ENDCOORD", 8 ) == 0 )
222  break;
223 
224  wxRealPoint coord( atof( param1 ), atof( param2 ) );
225  PolyEdges.push_back( coord );
226  }
227  }
228 
229  if( strncasecmp( Line, "XScale", 6 ) == 0 )
230  ShapeScaleX = atof( param2 );
231 
232  if( strncasecmp( Line, "YScale", 6 ) == 0 )
233  ShapeScaleY = atof( param2 );
234  }
235 
236  ShapeScaleX *= unitconv;
237  ShapeScaleY *= unitconv;
238 
239  m_SizeCtrl->SetValue( (int) ShapeScaleX, (int) ShapeScaleY );
240 }
241 
242 
244 {
245  PAD* pad1;
246  PAD* pad2;
248  wxString cmp_name;
249  int pad_count = 2;
250  FP_SHAPE* shape;
251 
252  PCB_EDIT_FRAME& editFrame = *getEditFrame<PCB_EDIT_FRAME>();
253 
254  MWAVE_POLYGONAL_SHAPE_DLG dlg( &editFrame, wxDefaultPosition );
255 
256  int ret = dlg.ShowModal();
257 
258  if( ret != wxID_OK )
259  {
260  PolyEdges.clear();
261  return NULL;
262  }
263 
264  if( PolyShapeType == 2 ) // mirrored
266 
269 
270  if( ( ShapeSize.x ) == 0 || ( ShapeSize.y == 0 ) )
271  {
272  editFrame.ShowInfoBarError( _( "Shape has a null size!" ) );
273  return NULL;
274  }
275 
276  if( PolyEdges.size() == 0 )
277  {
278  editFrame.ShowInfoBarError( _( "Shape has no points!" ) );
279  return NULL;
280  }
281 
282  cmp_name = wxT( "muwave_polygon" );
283 
284  // Create a footprint with 2 pads, orientation = 0, pos 0
285  footprint = createBaseFootprint( cmp_name, 0, pad_count );
286 
287  // We try to place the footprint anchor to the middle of the shape len
288  wxPoint offset;
289  offset.x = -ShapeSize.x / 2;
290 
291  auto it = footprint->Pads().begin();
292 
293  pad1 = *it;
294  pad1->SetX0( offset.x );
295  pad1->SetX( pad1->GetPos0().x );
296 
297  pad2 = *( ++it );
298  pad2->SetX0( offset.x + ShapeSize.x );
299  pad2->SetX( pad2->GetPos0().x );
300 
301  // Add a polygonal edge (corners will be added later) on copper layer
302  shape = new FP_SHAPE( footprint );
303  shape->SetShape( S_POLYGON );
304  shape->SetFilled( true );
305  shape->SetLayer( F_Cu );
306 
307  footprint->Add( shape, ADD_MODE::INSERT );
308 
309  // Get the corner buffer of the polygonal edge
310  std::vector<wxPoint> polyPoints;
311  polyPoints.reserve( PolyEdges.size() + 2 );
312 
313  // Init start point coord:
314  polyPoints.emplace_back( wxPoint( offset.x, 0 ) );
315 
316  wxPoint last_coordinate;
317 
318  for( wxRealPoint& pt: PolyEdges ) // Copy points
319  {
320  last_coordinate.x = KiROUND( pt.x * ShapeScaleX );
321  last_coordinate.y = -KiROUND( pt.y * ShapeScaleY );
322  last_coordinate += offset;
323  polyPoints.push_back( last_coordinate );
324  }
325 
326  // finish the polygonal shape
327  if( last_coordinate.y != 0 )
328  polyPoints.emplace_back( wxPoint( last_coordinate.x, 0 ) );
329 
330  switch( PolyShapeType )
331  {
332  case 0: // shape from file
333  case 2: // shape from file, mirrored (the mirror is already done)
334  break;
335 
336  case 1: // Symmetric shape: add the symmetric (mirrored) shape
337  for( int ndx = (int) polyPoints.size() - 1; ndx >= 0; --ndx )
338  {
339  wxPoint pt = polyPoints[ndx];
340  pt.y = -pt.y; // mirror about X axis
341  polyPoints.push_back( pt );
342  }
343  break;
344  }
345 
346  shape->SetPolyPoints( polyPoints );
347  // Set the polygon outline thickness to 0, only the polygonal shape is filled
348  // without extra thickness
349  shape->SetWidth( 0 );
350  PolyEdges.clear();
351 
353  editFrame.OnModify();
354  return footprint;
355 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:240
FOOTPRINT * createPolygonShape()
MWAVE_POLYGONAL_SHAPE_DLG(PCB_EDIT_FRAME *parent, const wxPoint &pos)
void OnModify() override
Function OnModify must be called after a board change to set the modified flag.
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:140
This file is part of the common library TODO brief description.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:40
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
Definition: board_item.h:206
Implementation of conversion functions that require both schematic and board internal units.
This file is part of the common library.
static constexpr double IU_PER_MM
Mock up a conversion function.
void SetFilled(bool aFlag)
Definition: pcb_shape.h:94
polygon (not yet used for tracks, but could be in microwave apps)
Definition: board_item.h:56
wxSize GetValue() const
PADS & Pads()
Definition: footprint.h:182
char * ReadLine() override
Function ReadLine reads a line of text into the buffer and increments the line number counter.
FILE_LINE_READER is a LINE_READER that reads from an open file.
Definition: richio.h:181
#define NULL
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:128
void OnOkClick(wxCommandEvent &event)
void ReadDataShapeDescr(wxCommandEvent &event)
Function ReadDataShapeDescr read a description shape file File format is Unit=MM XScale=271....
wxString EDA_FILE_SELECTOR(const wxString &aTitle, const wxString &aPath, const wxString &aFileName, const wxString &aExtension, const wxString &aWildcard, wxWindow *aParent, int aStyle, const bool aKeepWorkingDirectory, const wxPoint &aPosition, wxString *aMruPath)
Function EDA_FILE_SELECTOR.
Definition: gestfich.cpp:52
FOOTPRINT * footprint() const
void OnCancelClick(wxCommandEvent &event)
Helper dialog and control classes.
void SetX0(int x)
Definition: pad.h:223
static double ShapeScaleY
void ShowInfoBarError(const wxString &aErrorMsg)
static int PolyShapeType
const wxPoint & GetPos0() const
Definition: pad.h:220
#define _(s)
Definition: 3d_actions.cpp:33
FOOTPRINT * createBaseFootprint(const wxString &aValue, int aTextSize, int aPadCount)
Create a basic footprint for micro wave applications.
static std::vector< wxRealPoint > PolyEdges
PCB_EDIT_FRAME is the main frame for Pcbnew.
void SetWidth(int aWidth)
Definition: pcb_shape.h:117
#define IU_PER_MILS
Definition: plotter.cpp:137
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:68
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Definition: footprint.cpp:442
Definition: pad.h:59
FILTER_READER reads lines of text from another LINE_READER, but only returns non-comment lines and no...
Definition: filter_reader.h:37
void SetValue(int x_value, int y_value)
void SetPolyPoints(const std::vector< wxPoint > &aPoints)
Definition: pcb_shape.cpp:1046
Custom text control validator definitions.
static double ShapeScaleX
static wxSize ShapeSize
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
Definition: footprint.cpp:565
void SetX(int x)
Definition: pad.h:217