KiCad PCB EDA Suite
Loading...
Searching...
No Matches
zone_create_helper.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) 2017-2023 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <core/spinlock.h>
27#include <tool/tool_manager.h>
28#include <zone.h>
29#include <pcb_shape.h>
30#include <footprint.h>
31#include <board_commit.h>
33#include <pcb_painter.h>
34#include <tools/pcb_actions.h>
36
38 m_tool( aTool ),
39 m_params( aParams ),
40 m_parentView( *aTool.getView() )
41{
43}
44
45
47{
48 // remove the preview from the view
51}
52
53
55{
57 BOARD* board = frame->GetBoard();
58
59 // By default, new zones get the first unused priority
60 std::set<unsigned> priorities;
61
62 for( ZONE* zone : board->Zones() )
63 {
64 if( zone->GetTeardropAreaType() == TEARDROP_TYPE::TD_NONE
65 && ( zone->GetLayerSet() & LSET::AllCuMask() ).any()
66 && !zone->GetIsRuleArea() )
67 {
68 priorities.insert( zone->GetAssignedPriority() );
69 }
70 }
71
72 unsigned priority = 0;
73
74 for( unsigned exist_priority : priorities )
75 {
76 if( priority != exist_priority )
77 break;
78
79 ++priority;
80 }
81
82 aZoneInfo.m_ZonePriority = priority;
83}
84
85
86std::unique_ptr<ZONE> ZONE_CREATE_HELPER::createNewZone( bool aKeepout )
87{
89 BOARD* board = frame->GetBoard();
92 std::set<int> highlightedNets = board->GetHighLightNetCodes();
93
94 // Get the current default settings for zones
95 ZONE_SETTINGS zoneInfo = board->GetDesignSettings().GetDefaultZoneSettings();
96 zoneInfo.m_Layers.reset().set( m_params.m_layer ); // TODO(JE) multilayer defaults?
97 zoneInfo.m_NetcodeSelection = highlightedNets.empty() ? -1 : *highlightedNets.begin();
99
100 if( m_params.m_mode != ZONE_MODE::GRAPHIC_POLYGON
101 && ( zoneInfo.m_Layers & LSET::AllCuMask() ).any() )
102 {
103 setUniquePriority( zoneInfo );
104 }
105
106 // If we don't have a net from highlighting, maybe we can get one from the selection
108
109 if( selectionTool && !selectionTool->GetSelection().Empty()
110 && zoneInfo.m_NetcodeSelection == -1 )
111 {
112 EDA_ITEM* item = *selectionTool->GetSelection().GetItems().begin();
113
114 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
115 zoneInfo.m_NetcodeSelection = bci->GetNetCode();
116 }
117
118 if( m_params.m_mode != ZONE_MODE::GRAPHIC_POLYGON )
119 {
120 // Show options dialog
121 int dialogResult;
122
123 if( m_params.m_keepout )
124 dialogResult = InvokeRuleAreaEditor( frame, &zoneInfo );
125 else if( ( zoneInfo.m_Layers & LSET::AllCuMask() ).any() )
126 dialogResult = InvokeCopperZonesEditor( frame, &zoneInfo );
127 else
128 dialogResult = InvokeNonCopperZonesEditor( frame, &zoneInfo );
129
130 if( dialogResult == wxID_CANCEL )
131 return nullptr;
132
133 controls->WarpMouseCursor( controls->GetCursorPosition(), true );
134 frame->GetCanvas()->SetFocus();
135 }
136
137 wxASSERT( !m_tool.m_isFootprintEditor || ( parent->Type() == PCB_FOOTPRINT_T ) );
138
139 std::unique_ptr<ZONE> newZone = std::make_unique<ZONE>( parent );
140
141 // Apply the selected settings
142 zoneInfo.ExportSetting( *newZone );
143
144 return newZone;
145}
146
147
148std::unique_ptr<ZONE> ZONE_CREATE_HELPER::createZoneFromExisting( const ZONE& aSrcZone )
149{
150 BOARD* board = m_tool.getModel<BOARD>();
151
152 std::unique_ptr<ZONE> newZone = std::make_unique<ZONE>( board );
153
154 ZONE_SETTINGS zoneSettings;
155 zoneSettings << aSrcZone;
156
157 zoneSettings.ExportSetting( *newZone );
158
159 return newZone;
160}
161
162
163void ZONE_CREATE_HELPER::performZoneCutout( ZONE& aZone, const ZONE& aCutout )
164{
165 BOARD_COMMIT commit( &m_tool );
166 std::vector<ZONE*> newZones;
167
168 // Clear the selection before removing the old zone
169 auto toolMgr = m_tool.GetManager();
171
172 SHAPE_POLY_SET originalOutline( *aZone.Outline() );
173 originalOutline.BooleanSubtract( *aCutout.Outline(), SHAPE_POLY_SET::PM_FAST );
174
175 // After substracting the hole, originalOutline can have more than one main outline.
176 // But a zone can have only one main outline, so create as many zones as originalOutline
177 // contains main outlines:
178 for( int outline = 0; outline < originalOutline.OutlineCount(); outline++ )
179 {
180 auto newZoneOutline = new SHAPE_POLY_SET;
181 newZoneOutline->AddOutline( originalOutline.Outline( outline ) );
182
183 // Add holes (if any) to the new zone outline:
184 for (int hole = 0; hole < originalOutline.HoleCount( outline ) ; hole++ )
185 newZoneOutline->AddHole( originalOutline.CHole( outline, hole ) );
186
187 auto newZone = new ZONE( aZone );
188 newZone->SetOutline( newZoneOutline );
189 newZone->SetLocalFlags( 1 );
190 newZone->HatchBorder();
191 newZone->UnFill();
192 newZones.push_back( newZone );
193 commit.Add( newZone );
194 }
195
196 commit.Remove( &aZone );
197 commit.Push( _( "Add Zone Cutout" ) );
198
199 // Select the new zone and set it as the source for the next cutout
200 if( newZones.empty() )
201 {
202 m_params.m_sourceZone = nullptr;
203 }
204 else
205 {
206 m_params.m_sourceZone = newZones[0];
207 toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, newZones[0] );
208 }
209}
210
211
212void ZONE_CREATE_HELPER::commitZone( std::unique_ptr<ZONE> aZone )
213{
214 switch ( m_params.m_mode )
215 {
216 case ZONE_MODE::CUTOUT:
217 // For cutouts, subtract from the source
219 break;
220
221 case ZONE_MODE::ADD:
222 case ZONE_MODE::SIMILAR:
223 {
224 BOARD_COMMIT commit( &m_tool );
225
226 aZone->HatchBorder();
227
228 commit.Add( aZone.get() );
229 commit.Push( _( "Add a zone" ) );
230
232 break;
233 }
234
235 case ZONE_MODE::GRAPHIC_POLYGON:
236 {
237 BOARD_COMMIT commit( &m_tool );
238 BOARD* board = m_tool.getModel<BOARD>();
240 PCB_SHAPE* poly = new PCB_SHAPE( m_tool.m_frame->GetModel() );
241
242 poly->SetShape( SHAPE_T::POLY );
243 poly->SetFilled( layer != Edge_Cuts && layer != F_CrtYd && layer != B_CrtYd );
244
246 LINE_STYLE::SOLID ) );
247 poly->SetLayer( layer );
248 poly->SetPolyShape( *aZone->Outline() );
249
250 commit.Add( poly );
251 commit.Push( _( "Add Polygon" ) );
252
254 break;
255 }
256 }
257}
258
259
261{
262 // if we don't have a zone, create one
263 if( !m_zone )
264 {
267 else
269
270 if( m_zone )
271 {
273
274 // set up properties from zone
275 const auto& settings = *m_parentView.GetPainter()->GetSettings();
276 COLOR4D color = settings.GetColor( nullptr, m_zone->GetFirstLayer() );
277
278 m_previewItem.SetStrokeColor( COLOR4D::WHITE );
279 m_previewItem.SetFillColor( color.WithAlpha( 0.2 ) );
280
282
285 }
286 }
287
288 return m_zone != nullptr;
289}
290
291
293{
294 // Handle a cancel-interactive
295 if( m_zone && !aMgr.IsPolygonInProgress() )
296 {
297 m_zone = nullptr;
299 return;
300 }
301
302 // send the points to the preview item
304 aMgr.GetLoopLinePoints() );
306}
307
308
310{
311 auto& finalPoints = aMgr.GetLockedInPoints();
312
313 if( finalPoints.PointCount() < 3 )
314 {
315 // just scrap the zone in progress
316 m_zone = nullptr;
317 }
318 else
319 {
320 // if m_params.m_mode == DRAWING_TOOL::ZONE_MODE::CUTOUT, m_zone will be merged to the
321 // existing zone as a new hole.
322 m_zone->Outline()->NewOutline();
323 auto* outline = m_zone->Outline();
324
325 for( int i = 0; i < finalPoints.PointCount(); ++i )
326 outline->Append( finalPoints.CPoint( i ) );
327
328 // In DEG45 mode, we may have intermediate points in the leader that should be included
329 // as they are shown in the preview. These typically maintain the 45 constraint
331 {
332 const SHAPE_LINE_CHAIN leaderPts = aMgr.GetLeaderLinePoints();
333 for( int i = 1; i < leaderPts.PointCount(); i++ )
334 outline->Append( leaderPts.CPoint( i ) );
335
336 const SHAPE_LINE_CHAIN loopPts = aMgr.GetLoopLinePoints();
337 for( int i = 1; i < loopPts.PointCount() - 1; i++ )
338 outline->Append( loopPts.CPoint( i ) );
339 }
340
341 SHAPE_LINE_CHAIN& chain = outline->Outline( 0 );
342
343 chain.SetClosed( true );
344 chain.Simplify( true );
345
346 // Remove the start point if it lies on the line between neighbouring points.
347 // Simplify doesn't handle that currently.
348 if( chain.PointCount() >= 3 )
349 {
350 SEG seg( chain.CPoint( -1 ), chain.CPoint( 1 ) );
351
352 if( seg.LineDistance( chain.CPoint( 0 ) ) <= 1 )
353 chain.Remove( 0 );
354 }
355
356 // hand the zone over to the committer
357 commitZone( std::move( m_zone ) );
358 m_zone = nullptr;
359 }
360
362}
int color
Definition: DXF_plotter.cpp:58
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
Abstract interface for BOARD_ITEMs capable of storing other items inside.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:282
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:797
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been removed.
Definition: commit.h:92
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:80
Tool responsible for drawing graphical elements like lines, arcs, circles, etc.
Definition: drawing_tool.h:55
PCB_BASE_EDIT_FRAME * m_frame
Definition: drawing_tool.h:354
void SetFocus() override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:88
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
void SetFilled(bool aFlag)
Definition: eda_shape.h:96
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: eda_shape.h:270
void SetShape(SHAPE_T aShape)
Definition: eda_shape.h:119
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
void SetPoints(const SHAPE_LINE_CHAIN &aLockedInPts, const SHAPE_LINE_CHAIN &aLeaderPts, const SHAPE_LINE_CHAIN &aLoopPts)
Set the polygon points.
void SetFillColor(const COLOR4D &aNewColor)
Set the line width to set before drawing preview.
void SetStrokeColor(const COLOR4D &aNewColor)
Set the fill color to set before drawing preview.
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void WarpMouseCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
If enabled (.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:315
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:354
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1631
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:215
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1558
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:863
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:71
Common, abstract interface for edit frames.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
The selection tool: currently supports:
PCB_SELECTION & GetSelection()
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: pcb_shape.cpp:314
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: pcb_shape.h:86
virtual bool Is45Limited() const
Should the tool use its 45° mode option?
bool m_isFootprintEditor
Class that handles the drawing of a polygon, including management of last corner deletion and drawing...
const SHAPE_LINE_CHAIN & GetLockedInPoints() const
Get the "locked-in" points that describe the polygon itself.
@ DIRECT
Unconstrained point-to-point.
LEADER_MODE GetLeaderMode() const
void SetLeaderMode(LEADER_MODE aMode)
Set the leader mode to use when calculating the leader/returner lines.
const SHAPE_LINE_CHAIN & GetLoopLinePoints() const
Get the points from the current cursor position to the polygon start point.
const SHAPE_LINE_CHAIN & GetLeaderLinePoints() const
Get the points comprising the leader line (the line from the last locked-in point to the current curs...
Definition: seg.h:42
int LineDistance(const VECTOR2I &aP, bool aDetermineSide=false) const
Return the closest Euclidean distance between point aP and the line defined by the ends of segment (t...
Definition: seg.cpp:341
const std::deque< EDA_ITEM * > GetItems() const
Definition: selection.h:120
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:109
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Simplify(int aMaxError=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
Represent a set of closed polygons.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset difference For aFastMode meaning, see function booleanOp.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
int OutlineCount() const
Return the number of outlines in the set.
Simple container to manage line stroke parameters.
Definition: stroke_params.h:81
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:145
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition: tool_base.h:186
T * getModel() const
Return the model object if it matches the requested type.
Definition: tool_base.h:198
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:145
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:388
void commitZone(std::unique_ptr< ZONE > aZone)
Commit the current zone-in-progress to the BOARD.
PARAMS & m_params
The preview item to display.
bool OnFirstPoint(POLYGON_GEOM_MANAGER &aMgr) override
Called before the first point is added - clients can do initialization here, and can veto the start o...
ZONE_CREATE_HELPER(DRAWING_TOOL &aTool, PARAMS &aParams)
std::unique_ptr< ZONE > createNewZone(bool aKeepout)
Prompt the user for new zone settings, and create a new zone with those settings.
void performZoneCutout(ZONE &aZone, const ZONE &aCutout)
Cut one zone out of another one (i.e.
void setUniquePriority(ZONE_SETTINGS &aZoneInfo)
Choose a new priority for @aZoneInfo.
void OnGeometryChange(const POLYGON_GEOM_MANAGER &aMgr) override
Called when the polygon is complete.
std::unique_ptr< ZONE > m_zone
std::unique_ptr< ZONE > createZoneFromExisting(const ZONE &aSrcZone)
Create a new zone with the settings from an existing zone.
KIGFX::PREVIEW::POLYGON_ITEM m_previewItem
view that show the preview item
void OnComplete(const POLYGON_GEOM_MANAGER &aMgr) override
KIGFX::VIEW & m_parentView
The zone-in-progress.
DRAWING_TOOL & m_tool
Parameters of the zone to be drawn.
ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:71
void SetIsRuleArea(bool aEnable)
int m_NetcodeSelection
Definition: zone_settings.h:96
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
unsigned m_ZonePriority
Definition: zone_settings.h:82
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
SHAPE_POLY_SET * Outline()
Definition: zone.h:336
int InvokeCopperZonesEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings, CONVERT_SETTINGS *aConvertSettings)
Function InvokeCopperZonesEditor invokes up a modal dialog window for copper zone editing.
int InvokeNonCopperZonesEditor(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings, CONVERT_SETTINGS *aConvertSettings)
Function InvokeNonCopperZonesEditor invokes up a modal dialog window for non-copper zone editing.
int InvokeRuleAreaEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aZoneSettings, CONVERT_SETTINGS *aConvertSettings)
Function InvokeRuleAreaEditor invokes up a modal dialog window for copper zone editing.
#define _(s)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_CrtYd
Definition: layer_ids.h:117
@ Edge_Cuts
Definition: layer_ids.h:113
@ B_CrtYd
Definition: layer_ids.h:116
@ GEOMETRY
Position or shape has changed.
Definition: view_item.h:54
Parameters used to fully describe a zone creation process.
ZONE_MODE m_mode
Zone settings source (for similar and cutout zones)
bool m_keepout
< Should create a keepout zone?
ZONE * m_sourceZone
Zone leader mode.
PCB_LAYER_ID m_layer
The zone mode to operate in.
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86