KiCad PCB EDA Suite
Loading...
Searching...
No Matches
gerber_to_polyset.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) 2025 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "gerber_to_polyset.h"
21#include "gerber_file_image.h"
22#include "gerber_draw_item.h"
23#include "dcode.h"
25
26
28{
29 SHAPE_POLY_SET mergedPolygons;
30
31 if( !aImage )
32 return mergedPolygons;
33
34 // Accumulate positive and negative items separately, then perform a single boolean
35 // pass for each. This is O(N log N) vs O(N²) for per-item BooleanAdd.
36 SHAPE_POLY_SET positivePolygons;
37 SHAPE_POLY_SET negativePolygons;
38
39 for( GERBER_DRAW_ITEM* item : aImage->GetItems() )
40 {
41 SHAPE_POLY_SET itemPoly;
42 bool needsFlashOffset = false;
43
44 if( item->m_ShapeAsPolygon.OutlineCount() > 0 )
45 {
46 itemPoly = item->m_ShapeAsPolygon;
47 }
48 else if( item->m_ShapeType == GBR_SEGMENT )
49 {
50 D_CODE* dcode = item->GetDcodeDescr();
51
52 if( dcode && dcode->m_ApertType != APT_RECT )
53 {
54 int arcError = static_cast<int>( gerbIUScale.IU_PER_MM * ARC_LOW_DEF_MM );
55 TransformOvalToPolygon( itemPoly, item->m_Start, item->m_End,
56 item->m_Size.x, arcError, ERROR_INSIDE );
57 }
58 else
59 {
60 item->ConvertSegmentToPolygon( &itemPoly );
61 }
62 }
63 else if( item->m_ShapeType == GBR_ARC )
64 {
65 item->ConvertSegmentToPolygon( &itemPoly );
66 }
67 else if( item->m_Flashed )
68 {
69 D_CODE* dcode = item->GetDcodeDescr();
70
71 if( dcode )
72 {
73 dcode->ConvertShapeToPolygon( item );
74 itemPoly = dcode->m_Polygon;
75 needsFlashOffset = true;
76 }
77 }
78
79 if( itemPoly.OutlineCount() == 0 )
80 continue;
81
82 // Flashed shapes from ConvertShapeToPolygon are centered at (0,0).
83 // Offset by the item's position before applying the AB transform.
84 VECTOR2I offset = needsFlashOffset ? VECTOR2I( item->m_Start ) : VECTOR2I( 0, 0 );
85
86 SHAPE_POLY_SET& dest = item->GetLayerPolarity() ? negativePolygons : positivePolygons;
87
88 for( int i = 0; i < itemPoly.OutlineCount(); i++ )
89 {
90 const SHAPE_LINE_CHAIN& outline = itemPoly.COutline( i );
91 dest.NewOutline();
92
93 for( int j = 0; j < outline.PointCount(); j++ )
94 dest.Append( item->GetABPosition( outline.CPoint( j ) + offset ) );
95
96 for( int h = 0; h < itemPoly.HoleCount( i ); h++ )
97 {
98 const SHAPE_LINE_CHAIN& hole = itemPoly.CHole( i, h );
99 dest.NewHole();
100
101 for( int j = 0; j < hole.PointCount(); j++ )
102 dest.Append( item->GetABPosition( hole.CPoint( j ) + offset ) );
103 }
104 }
105 }
106
107 // Single-pass union of all positive items
108 positivePolygons.Simplify();
109
110 if( negativePolygons.OutlineCount() > 0 )
111 {
112 negativePolygons.Simplify();
113 positivePolygons.BooleanSubtract( negativePolygons );
114 }
115
116 mergedPolygons = std::move( positivePolygons );
117
118 if( aTolerance > 0 )
119 mergedPolygons.Inflate( aTolerance, CORNER_STRATEGY::ROUND_ALL_CORNERS, 16 );
120
121 return mergedPolygons;
122}
@ ERROR_INSIDE
constexpr EDA_IU_SCALE gerbIUScale
Definition base_units.h:111
constexpr double ARC_LOW_DEF_MM
Definition base_units.h:118
A gerber DCODE (also called Aperture) definition.
Definition dcode.h:80
APERTURE_T m_ApertType
Aperture type ( Line, rectangle, circle, oval poly, macro )
Definition dcode.h:202
SHAPE_POLY_SET m_Polygon
Definition dcode.h:217
void ConvertShapeToPolygon(const GERBER_DRAW_ITEM *aParent)
Convert a shape to an equivalent polygon.
Definition dcode.cpp:297
Hold the image data and parameters for one gerber file and layer parameters.
GERBER_DRAW_ITEMS & GetItems()
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int NewHole(int aOutline=-1)
Creates a new hole in a given outline.
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
int OutlineCount() const
Return the number of outlines in the set.
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
@ ROUND_ALL_CORNERS
All angles are rounded.
@ APT_RECT
Definition dcode.h:50
@ GBR_SEGMENT
@ GBR_ARC
SHAPE_POLY_SET ConvertGerberToPolySet(GERBER_FILE_IMAGE *aImage, int aTolerance)
Convert a GERBER_FILE_IMAGE to a merged SHAPE_POLY_SET.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687