KiCad PCB EDA Suite
Loading...
Searching...
No Matches
gerber_file_image.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) 1992-2019 Jean-Pierre Charras jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <gerbview.h>
26#include <gerbview_frame.h>
27#include <gerber_file_image.h>
28#include <gerber_to_polyset.h>
29#include <macros.h>
31#include <algorithm>
32#include <map>
33//#include <numeric>
34#include <core/arraydim.h>
35#include <core/profile.h>
36
37
42extern int scaletoIU( double aCoord, bool isMetric ); // defined it rs274d_read_XY_and_IJ_coordinates.cpp
43
44/* Format Gerber: NOTES:
45 * Tools and D_CODES
46 * tool number (identification of shapes)
47 * 1 to 999
48 *
49 * D_CODES:
50 * D01 ... D9 = action codes:
51 * D01 = activating light (lower pen) when di placement
52 * D02 = light extinction (lift pen) when di placement
53 * D03 Flash
54 * D09 = VAPE Flash
55 * D10 ... = Identification Tool (Opening)
56 *
57 * For tools:
58 * DCode min = D10
59 * DCode max = 999
60 */
61
62
67
68
72
73
75{
76 m_LayerName = wxT( "no name" ); // Layer name from the LN command
77 m_LayerNegative = false; // true = Negative Layer
78 m_StepForRepeat.x = m_StepForRepeat.y = 0; // X and Y offsets for Step and Repeat command
79 m_XRepeatCount = 1; // The repeat count on X axis
80 m_YRepeatCount = 1; // The repeat count on Y axis
81 m_StepForRepeatMetric = false; // false = Inches, true = metric
82}
83
84
86 EDA_ITEM( nullptr, GERBER_IMAGE_T )
87{
88 m_GraphicLayer = aLayer; // Graphic layer Number
89 m_PositiveDrawColor = WHITE; // The color used to draw positive items for this image
90
92 m_FileFunction = nullptr; // file function parameters
93
95
96 m_ApertureList.clear();
97}
98
99
101{
102 // Reverse iteration to avoid O(N^2) memcpy in a vector erase downstream.
103 // It results in a O(N^2) std::find, which is somewhat faster.
104 for( auto it = GetItems().rbegin(); it < GetItems().rend(); it++ )
105 delete *it;
106
107 m_drawings.clear();
108
109 for( const auto& ap_item : m_ApertureList )
110 delete ap_item.second;
111
112 delete m_FileFunction;
113}
114
115
116void GERBER_FILE_IMAGE::AddMessageToList( const wxString& aMessage )
117{
118 /* Add a message to the message list, but only if there are less than max_messages
119 * to avoid very long list (can happens if trying to read a non gerber file)
120 */
121 const int max_messages = 50; // Arbitrary but reasonable value.
122
123 if( m_messagesList.size() < max_messages )
124 m_messagesList.Add( aMessage );
125 else if( m_messagesList.size() == max_messages )
126 m_messagesList.Add( _( "Too many messages, some are skipped" ) );
127}
128
129
131{
132 m_DisplayOffset.x = KiROUND( aOffsetMM.x * gerbIUScale.IU_PER_MM );
133 m_DisplayOffset.y = KiROUND( aOffsetMM.y * gerbIUScale.IU_PER_MM );
134 m_DisplayRotation = aRotation;
135
136 // Clear m_AbsolutePolygon member of Gerber items, because draw coordinates
137 // are now outdated
138 for( GERBER_DRAW_ITEM* item : GetItems() )
139 item->m_AbsolutePolygon.RemoveAllContours();
140}
141
142
143D_CODE* GERBER_FILE_IMAGE::GetDCODEOrCreate( int aDCODE, bool aCreateIfNoExist )
144{
145 auto it = m_ApertureList.find( aDCODE );
146
147 if( it != m_ApertureList.end() )
148 return it->second;
149
150 // lazily create the D_CODE if it does not exist.
151 if( aCreateIfNoExist )
152 {
153 D_CODE* dcode = new D_CODE( aDCODE );
154 m_ApertureList.insert( { aDCODE, dcode } );
155 return dcode;
156 }
157
158 return nullptr;
159}
160
161
163{
164 auto it = m_ApertureList.find( aDCODE );
165
166 if( it != m_ApertureList.end() )
167 return it->second;
168
169 return nullptr;
170}
171
172
174{
175 APERTURE_MACRO_SET::iterator iter = m_aperture_macros.find( aLookup );
176
177 if( iter != m_aperture_macros.end() )
178 {
179 APERTURE_MACRO* pam = (APERTURE_MACRO*) &( *iter );
180 return pam;
181 }
182
183 return nullptr; // not found
184}
185
186
188{
189 m_InUse = false;
190 m_GBRLayerParams.ResetDefaultValues();
191 m_FileName.Empty();
192 m_ImageName = wxEmptyString; // Image name from the IN command (deprecated)
193 m_ImageNegative = false; // true = Negative image
194 m_IsX2_file = false; // true only if a %TF, %TA or %TD command
195 delete m_FileFunction; // file function parameters
196 m_FileFunction = nullptr;
197 m_MD5_value.Empty(); // MD5 value found in a %TF.MD5 command
198 m_PartString.Empty(); // string found in a %TF.Part command
199 m_hasNegativeItems = -1; // set to uninitialized
200 m_ImageJustifyOffset = VECTOR2I( 0, 0 ); // Image justify Offset
201 m_ImageJustifyXCenter = false; // Image Justify Center on X axis (default = false)
202 m_ImageJustifyYCenter = false; // Image Justify Center on Y axis (default = false)
203 m_GerbMetric = false; // false = Inches (default), true = metric
204 m_Relative = false; // false = absolute Coord,
205 // true = relative Coord
206 m_NoTrailingZeros = false; // true: trailing zeros deleted
207 m_ImageOffset.x = m_ImageOffset.y = 0; // Coord Offset, from IO command
208 m_ImageRotation = 0; // Allowed 0, 90, 180, 270 (in degree)
209 m_LocalRotation = 0.0; // Layer rotation from RO command (in 0.1 degree)
210 m_Offset.x = 0;
211 m_Offset.y = 0; // Coord Offset, from OF command
212 m_Scale.x = m_Scale.y = 1.0; // scale (A and B) this layer
213 m_MirrorA = false; // true: mirror / axe A (default = X)
214 m_MirrorB = false; // true: mirror / axe B (default = Y)
215 m_SwapAxis = false; // false if A = X, B = Y; true if A =Y, B = Y
216 m_Has_DCode = false; // true = DCodes in file
217 // false = no DCode-> perhaps deprecated RS274D file
218 m_Has_MissingDCode = false; // true = some D_Codes are used, but not defined
219 // perhaps deprecated RS274D file
220 m_FmtScale.x = m_FmtScale.y = 4; // Initialize default format to 3.4 => 4
221 m_FmtLen.x = m_FmtLen.y = 3 + 4; // Initialize default format len = 3+4
222
223 m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Linear, 90 arc, Circ.
224 m_360Arc_enbl = true; // 360 deg circular mode (G75) selected as default
225 // interpolation disable
226 m_AsArcG74G75Cmd = false; // false until a G74 or G75 command is found
227 m_Current_Tool = 0; // Current Dcode selected
228 m_CommandState = 0; // State of the current command
229 m_CurrentPos.x = m_CurrentPos.y = 0; // current specified coord
230 m_PreviousPos.x = m_PreviousPos.y = 0; // last specified coord
231 m_IJPos.x = m_IJPos.y = 0; // current centre coord for
232 // plot arcs & circles
233 m_LastCoordIsIJPos = false; // True only after a IJ coordinate is read
234 m_ArcRadius = 0; // radius of arcs in circular interpol (given by A## command).
235 // in command like X##Y##A##
236 m_LastArcDataType = ARC_INFO_TYPE_NONE; // Extra coordinate info type for arcs
237 // (radius or IJ center coord)
238 m_LineNum = 0; // line number in file being read
239 m_Current_File = nullptr; // Gerber file to read
240 m_PolygonFillMode = false;
242 m_Selected_Tool = 0;
244 m_Exposure = false;
245
248}
249
250
251/* Function HasNegativeItems
252 * return true if at least one item must be drawn in background color
253 * used to optimize screen refresh
254 */
256{
257 if( m_hasNegativeItems < 0 ) // negative items are not yet searched: find them if any
258 {
259 if( m_ImageNegative ) // A negative layer is expected having always negative objects.
260 {
262 }
263 else
264 {
266
267 for( GERBER_DRAW_ITEM* item : GetItems() )
268 {
269 if( item->GetLayer() != m_GraphicLayer )
270 continue;
271
272 if( item->HasNegativeItems() )
273 {
275 break;
276 }
277 }
278 }
279 }
280
281 return m_hasNegativeItems == 1;
282}
283
285{
286 int count = 0;
287
288 for( const auto& n : m_ApertureList )
289 {
290 D_CODE* dcode = n.second;
291
292 wxCHECK2( dcode, continue );
293
294 if( dcode->m_InUse || dcode->m_Defined )
295 count++;
296 }
297
298 return count;
299}
300
301
311{
312 if( GetLayerParams().m_XRepeatCount < 2 && GetLayerParams().m_YRepeatCount < 2 )
313 return; // Nothing to repeat
314
315 // Duplicate item:
316 for( int ii = 0; ii < GetLayerParams().m_XRepeatCount; ii++ )
317 {
318 for( int jj = 0; jj < GetLayerParams().m_YRepeatCount; jj++ )
319 {
320 // the first gerber item already exists (this is the template)
321 // create duplicate only if ii or jj > 0
322 if( jj == 0 && ii == 0 )
323 continue;
324
325 GERBER_DRAW_ITEM* dupItem = new GERBER_DRAW_ITEM( aItem );
326 VECTOR2I move_vector;
327 move_vector.x =
328 scaletoIU( ii * GetLayerParams().m_StepForRepeat.x, GetLayerParams().m_StepForRepeatMetric );
329 move_vector.y =
330 scaletoIU( jj * GetLayerParams().m_StepForRepeat.y, GetLayerParams().m_StepForRepeatMetric );
331 dupItem->MoveXY( move_vector );
332 AddItemToList( dupItem );
333 }
334 }
335}
336
337
348{
349 wxString msg;
350
351 aMainFrame->ClearMsgPanel();
352
353 // Display the Gerber variant (X1 / X2
354 aMainFrame->AppendMsgPanel( _( "Format" ), m_IsX2_file ? wxT( "X2" ) : wxT( "X1" ) );
355
356 // Display Image name (Image specific). IM command (Image Name) is deprecated
357 // So non empty image name is very rare, probably never found
358 if( !m_ImageName.IsEmpty() )
359 aMainFrame->AppendMsgPanel( _( "Image name" ), m_ImageName );
360
361 // Display graphic layer number used to draw this Image
362 // (not a Gerber parameter but is also image specific)
363 msg.Printf( wxT( "%d" ), m_GraphicLayer + 1 );
364 aMainFrame->AppendMsgPanel( _( "Graphic layer" ), msg );
365
366 // Display Image rotation (Image specific)
367 msg.Printf( wxT( "%d" ), m_ImageRotation );
368 aMainFrame->AppendMsgPanel( _( "Img Rot." ), msg );
369
370 // Display Image polarity (Image specific)
371 msg = m_ImageNegative ? _( "Negative" ) : _( "Normal" );
372 aMainFrame->AppendMsgPanel( _( "Polarity" ), msg );
373
374 // Display Image justification and offset for justification (Image specific)
375 msg = m_ImageJustifyXCenter ? _( "Center" ) : _( "Normal" );
376 aMainFrame->AppendMsgPanel( _( "X Justify" ), msg );
377
378 msg = m_ImageJustifyYCenter ? _( "Center" ) : _( "Normal" );
379 aMainFrame->AppendMsgPanel( _( "Y Justify" ), msg );
380
381 msg.Printf( wxT( "X=%s Y=%s" ), aMainFrame->MessageTextFromValue( m_ImageJustifyOffset.x ),
383
384 aMainFrame->AppendMsgPanel( _( "Image Justify Offset" ), msg );
385}
386
387
389{
390 SHAPE_POLY_SET merged = ConvertGerberToPolySet( this );
391 constexpr double IU2_TO_MM2 = 1e-10;
392 return merged.Area() * IU2_TO_MM2;
393}
394
395
397{
398 /* Called when a %TD command is found
399 * Remove the attribute specified by the %TD command.
400 * is no attribute, all current attributes specified by the %TO and the %TA
401 * commands are cleared.
402 * if a attribute name is specified (for instance %TD.CN*%) is specified,
403 * only this attribute is cleared
404 */
405 wxString cmd = aAttribute.GetPrm( 0 );
406 m_NetAttributeDict.ClearAttribute( &cmd );
407
408 if( cmd.IsEmpty() || cmd == wxT( ".AperFunction" ) )
409 m_AperFunction.Clear();
410}
411
412
413INSPECT_RESULT GERBER_FILE_IMAGE::Visit( INSPECTOR inspector, void* testData, const std::vector<KICAD_T>& aScanTypes )
414{
415 for( KICAD_T scanType : aScanTypes )
416 {
417 if( scanType == GERBER_DRAW_ITEM_T )
418 {
419 if( IterateForward( GetItems(), inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
421 }
422 }
423
425}
int scaletoIU(double aCoord, bool isMetric)
Convert a distance given in floating point to our internal units.
constexpr EDA_IU_SCALE gerbIUScale
Definition base_units.h:124
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
Support the "aperture macro" defined within standard RS274X.
A gerber DCODE (also called Aperture) definition.
Definition dcode.h:80
bool m_Defined
false if the aperture is not defined in the header
Definition dcode.h:213
bool m_InUse
false if the aperture (previously defined) is not used to draw something
Definition dcode.h:211
virtual void ClearMsgPanel()
Clear all messages from the message panel.
void AppendMsgPanel(const wxString &aTextUpper, const wxString &aTextLower, int aPadding=6)
Append a message to the message panel.
static INSPECT_RESULT IterateForward(std::deque< T > &aList, INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &scanTypes)
This changes first parameter to avoid the DList and use the main queue instead.
Definition eda_item.h:332
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:41
void MoveXY(const VECTOR2I &aMoveVector)
Move this object.
void SetDrawOffetAndRotation(VECTOR2D aOffsetMM, EDA_ANGLE aRotation)
Set the offset and rotation to draw a file image Does not change any coordinate od draw items.
int m_Last_Pen_Command
Current or last pen state (0..9, set by Dn option with n < 10.
APERTURE_MACRO * FindApertureMacro(const APERTURE_MACRO &aLookup)
Look up a previously read in aperture macro.
X2_ATTRIBUTE_FILEFUNCTION * m_FileFunction
file function parameters, found in a TF command or a G04
void RemoveAttribute(X2_ATTRIBUTE &aAttribute)
Called when a TD command is found the Gerber file.
int m_hasNegativeItems
True if the image is negative or has some negative items.
virtual void ResetDefaultValues()
Set all parameters to a default value, before reading a file.
bool m_SwapAxis
false if A = X and B = Y (default); true if A = Y, B = X
double m_LocalRotation
Local rotation added to m_ImageRotation.
VECTOR2I m_Offset
Coord Offset, from OF command.
wxSize m_FmtScale
Fmt 2.3: m_FmtScale = 3, fmt 3.4: m_FmtScale = 4.
int m_ArcRadius
Identifier for arc data type (IJ (center) or A## (radius)).
wxString m_FileName
Full File Name for this layer.
void StepAndRepeatItem(const GERBER_DRAW_ITEM &aItem)
Gerber format has a command Step an Repeat.
bool m_ImageJustifyXCenter
Image Justify Center on X axis (default = false)
bool m_ImageJustifyYCenter
Image Justify Center on Y axis (default = false)
VECTOR2I m_DisplayOffset
< Parameters used only to draw (display) items on this layer.
VECTOR2I m_PreviousPos
old current specified coord for plot
bool m_InUse
true if this image is currently in use (a file is loaded in it) false if it must be not drawn
bool m_ImageNegative
true = Negative image
void AddMessageToList(const wxString &aMessage)
Add a message to the message list.
LAST_EXTRA_ARC_DATA_TYPE m_LastArcDataType
wxArrayString m_messagesList
int m_LineNum
Line number of the gerber file while reading.
COLOR4D m_PositiveDrawColor
The color used to draw positive items.
std::map< int, D_CODE * > m_ApertureList
Dcode (Aperture) List for this layer (see dcode.h)
VECTOR2I m_IJPos
IJ coord (for arcs & circles )
wxString m_ImageName
Image name, from IN <name>* command.
bool m_Relative
false = absolute Coord, true = relative Coord.
wxString m_MD5_value
MD5 value found in a TF.MD5 command.
bool m_MirrorB
true: mirror / axis B (Y)
wxString m_PartString
string found in a TF.Part command
D_CODE * GetDCODE(int aDCODE) const
Return a pointer to the D_CODE within this GERBER for the given aDCODE.
double CalculateCopperArea()
Calculate the total copper area in the image.
bool m_IsX2_file
True if a X2 gerber attribute was found in file.
int m_ImageRotation
Image rotation (0, 90, 180, 270 only) in degrees.
VECTOR2I m_ImageOffset
Coord Offset, from IO command.
int m_PolygonFillModeState
a collection of APERTURE_MACROS, sorted by name
bool m_Has_DCode
< True if has DCodes in file or false if no DCodes found. Perhaps deprecated RS274D file.
int m_Current_Tool
Current Tool (Dcode) number selected.
D_CODE * GetDCODEOrCreate(int aDCODE, bool aCreateIfNoExist=true)
Return a pointer to the D_CODE within this GERBER for the given aDCODE.
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &aScanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
void AddItemToList(GERBER_DRAW_ITEM *aItem)
Add a new GERBER_DRAW_ITEM item to the drawings list.
wxSize m_FmtLen
Nb chars per coord. ex fmt 2.3, m_FmtLen = 5.
int m_GraphicLayer
Graphic layer Number.
APERTURE_MACRO_SET m_aperture_macros
GERBER_DRAW_ITEMS m_drawings
bool m_GerbMetric
false = Inches, true = metric
GBR_NETLIST_METADATA m_NetAttributeDict
int m_CommandState
state of gerber analysis command
bool m_NoTrailingZeros
true: remove tailing zeros.
int m_Iterpolation
Linear, 90 arc, Circ.
VECTOR2I m_CurrentPos
current specified coord for plot
bool m_MirrorA
true: mirror / axis A (X)
bool m_LastCoordIsIJPos
A value ( = radius in circular routing in Excellon files ).
VECTOR2I m_Scale
scale (X and Y) of layer.
GERBER_DRAW_ITEMS & GetItems()
VECTOR2I m_ImageJustifyOffset
Image Justify Offset on XY axis (default = 0,0)
GERBER_LAYER m_GBRLayerParams
GERBER_LAYER & GetLayerParams()
void DisplayImageInfo(GERBVIEW_FRAME *aMainFrame)
Display information about image parameters in the status bar.
wxRealPoint m_StepForRepeat
Represent a set of closed polygons.
double Area()
Return the area of this poly set.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
The attribute value consists of a number of substrings separated by a comma.
const wxString & GetPrm(int aIdx)
@ WHITE
Definition color4d.h:48
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
INSPECT_RESULT
Definition eda_item.h:46
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:93
int scaletoIU(double aCoord, bool isMetric)
Function scaletoIU converts a distance given in floating point to our internal units.
@ ARC_INFO_TYPE_NONE
SHAPE_POLY_SET ConvertGerberToPolySet(GERBER_FILE_IMAGE *aImage, int aTolerance)
Convert a GERBER_FILE_IMAGE to a merged SHAPE_POLY_SET.
@ GERB_INTERPOL_LINEAR_1X
Definition gerbview.h:35
This file contains miscellaneous commonly used macros and functions.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:75
@ GERBER_DRAW_ITEM_T
Definition typeinfo.h:211
@ GERBER_IMAGE_T
Definition typeinfo.h:212
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
VECTOR2< double > VECTOR2D
Definition vector2d.h:686