KiCad PCB EDA Suite
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-2019 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 <fp_shape.h>
32#include <board_commit.h>
34#include <pcb_painter.h>
35#include <pcbnew_settings.h>
36#include <tools/pcb_actions.h>
38#include <zone_filler.h>
39
41 m_tool( aTool ),
42 m_params( aParams ),
43 m_parentView( *aTool.getView() )
44{
46}
47
48
50{
51 // remove the preview from the view
54}
55
56
58{
60 BOARD* board = frame->GetBoard();
61
62 // By default, new zones get the first unused priority
63 std::set<unsigned> priorities;
64
65 for( ZONE* zone : board->Zones() )
66 {
67 if( zone->GetTeardropAreaType() == TEARDROP_TYPE::TD_NONE
68 && ( zone->GetLayerSet() & LSET::AllCuMask() ).any()
69 && !zone->GetIsRuleArea() )
70 {
71 priorities.insert( zone->GetAssignedPriority() );
72 }
73 }
74
75 unsigned priority = 0;
76
77 for( unsigned exist_priority : priorities )
78 {
79 if( priority != exist_priority )
80 break;
81
82 ++priority;
83 }
84
85 aZoneInfo.m_ZonePriority = priority;
86}
87
88
89std::unique_ptr<ZONE> ZONE_CREATE_HELPER::createNewZone( bool aKeepout )
90{
92 BOARD* board = frame->GetBoard();
95 std::set<int> highlightedNets = board->GetHighLightNetCodes();
96
97 // Get the current default settings for zones
98 ZONE_SETTINGS zoneInfo = frame->GetZoneSettings();
99 zoneInfo.m_Layers.reset().set( m_params.m_layer ); // TODO(JE) multilayer defaults?
100 zoneInfo.m_NetcodeSelection = highlightedNets.empty() ? -1 : *highlightedNets.begin();
101 zoneInfo.SetIsRuleArea( m_params.m_keepout );
102
104 && ( zoneInfo.m_Layers & LSET::AllCuMask() ).any() )
105 {
106 setUniquePriority( zoneInfo );
107 }
108
109 // If we don't have a net from highlighting, maybe we can get one from the selection
111
112 if( selectionTool && !selectionTool->GetSelection().Empty()
113 && zoneInfo.m_NetcodeSelection == -1 )
114 {
115 EDA_ITEM* item = *selectionTool->GetSelection().GetItems().begin();
116
117 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
118 zoneInfo.m_NetcodeSelection = bci->GetNetCode();
119 }
120
122 {
123 // Get the current default settings for zones
124
125 // Show options dialog
126 int dialogResult;
127
128 if( m_params.m_keepout )
129 dialogResult = InvokeRuleAreaEditor( frame, &zoneInfo );
130 else
131 {
132 // TODO(JE) combine these dialogs?
133 if( ( zoneInfo.m_Layers & LSET::AllCuMask() ).any() )
134 dialogResult = InvokeCopperZonesEditor( frame, &zoneInfo );
135 else
136 dialogResult = InvokeNonCopperZonesEditor( frame, &zoneInfo );
137 }
138
139 if( dialogResult == wxID_CANCEL )
140 return nullptr;
141
142 controls->WarpMouseCursor( controls->GetCursorPosition(), true );
143 }
144
145 // The new zone is a ZONE if created in the board editor and a FP_ZONE if created in the
146 // footprint editor
147 wxASSERT( !m_tool.m_isFootprintEditor || ( parent->Type() == PCB_FOOTPRINT_T ) );
148
149 std::unique_ptr<ZONE> newZone = m_tool.m_isFootprintEditor ?
150 std::make_unique<FP_ZONE>( parent ) :
151 std::make_unique<ZONE>( parent );
152
153 // Apply the selected settings
154 zoneInfo.ExportSetting( *newZone );
155
156 return newZone;
157}
158
159
160std::unique_ptr<ZONE> ZONE_CREATE_HELPER::createZoneFromExisting( const ZONE& aSrcZone )
161{
162 BOARD* board = m_tool.getModel<BOARD>();
163
164 std::unique_ptr<ZONE> newZone = std::make_unique<ZONE>( board );
165
166 ZONE_SETTINGS zoneSettings;
167 zoneSettings << aSrcZone;
168
169 zoneSettings.ExportSetting( *newZone );
170
171 return newZone;
172}
173
174
175void ZONE_CREATE_HELPER::performZoneCutout( ZONE& aZone, const ZONE& aCutout )
176{
177 BOARD_COMMIT commit( &m_tool );
178 std::vector<ZONE*> newZones;
179
180 // Clear the selection before removing the old zone
181 auto toolMgr = m_tool.GetManager();
182 toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
183
184 SHAPE_POLY_SET originalOutline( *aZone.Outline() );
185 originalOutline.BooleanSubtract( *aCutout.Outline(), SHAPE_POLY_SET::PM_FAST );
186
187 // After substracting the hole, originalOutline can have more than one
188 // main outline.
189 // But a zone can have only one main outline, so create as many zones as
190 // originalOutline contains main outlines:
191 for( int outline = 0; outline < originalOutline.OutlineCount(); outline++ )
192 {
193 auto newZoneOutline = new SHAPE_POLY_SET;
194 newZoneOutline->AddOutline( originalOutline.Outline( outline ) );
195
196 // Add holes (if any) to thez new zone outline:
197 for (int hole = 0; hole < originalOutline.HoleCount( outline ) ; hole++ )
198 newZoneOutline->AddHole( originalOutline.CHole( outline, hole ) );
199
200 auto newZone = new ZONE( aZone );
201 newZone->SetOutline( newZoneOutline );
202 newZone->SetLocalFlags( 1 );
203 newZone->HatchBorder();
204 newZone->UnFill();
205 newZones.push_back( newZone );
206 commit.Add( newZone );
207 }
208
209 commit.Remove( &aZone );
210
211 // TODO Refill zones when KiCad supports auto re-fill
212
213 commit.Push( _( "Add a zone cutout" ) );
214
215 // Select the new zone and set it as the source for the next cutout
216 if( newZones.empty() )
217 {
218 m_params.m_sourceZone = nullptr;
219 }
220 else
221 {
222 m_params.m_sourceZone = newZones[0];
223 toolMgr->RunAction( PCB_ACTIONS::selectItem, true, newZones[0] );
224 }
225
226}
227
228
229void ZONE_CREATE_HELPER::commitZone( std::unique_ptr<ZONE> aZone )
230{
231 switch ( m_params.m_mode )
232 {
234 // For cutouts, subtract from the source
236 break;
237
238 case ZONE_MODE::ADD:
240 {
241 BOARD_COMMIT commit( &m_tool );
242
243 aZone->HatchBorder();
244
245 commit.Add( aZone.get() );
246 commit.Push( _( "Add a zone" ) );
247
248 m_tool.GetManager()->RunAction( PCB_ACTIONS::selectItem, true, aZone.release() );
249 break;
250 }
251
253 {
254 BOARD_COMMIT commit( &m_tool );
255 BOARD* board = m_tool.getModel<BOARD>();
257 PCB_SHAPE* poly;
258
260 poly = new FP_SHAPE( static_cast<FOOTPRINT*>( m_tool.m_frame->GetModel() ) );
261 else
262 poly = new PCB_SHAPE();
263
264 poly->SetShape( SHAPE_T::POLY );
265
266 if( layer == Edge_Cuts || layer == F_CrtYd || layer == B_CrtYd )
267 poly->SetFilled( false );
268 else
269 poly->SetFilled( true );
270
273 poly->SetLayer( layer );
274 poly->SetPolyShape( *aZone->Outline() );
275
276 commit.Add( poly );
278
279 commit.Push( _( "Add a graphical polygon" ) );
280
281 break;
282 }
283 }
284}
285
286
288{
289 // if we don't have a zone, create one
290 // the user's choice here can affect things like the colour of the preview
291 if( !m_zone )
292 {
295 else
297
298 if( m_zone )
299 {
301
302 // set up properties from zone
303 const auto& settings = *m_parentView.GetPainter()->GetSettings();
304 COLOR4D color = settings.GetColor( nullptr, m_zone->GetFirstLayer() );
305
307 m_previewItem.SetFillColor( color.WithAlpha( 0.2 ) );
308
310
313 }
314 }
315
316 return m_zone != nullptr;
317}
318
319
321{
322 // send the points to the preview item
325}
326
327
329{
330 auto& finalPoints = aMgr.GetLockedInPoints();
331
332 if( finalPoints.PointCount() < 3 )
333 {
334 // just scrap the zone in progress
335 m_zone = nullptr;
336 }
337 else
338 {
339 // if m_params.m_mode == DRAWING_TOOL::ZONE_MODE::CUTOUT, m_zone
340 // will be merged to the existing zone as a new hole.
341 m_zone->Outline()->NewOutline();
342 auto* outline = m_zone->Outline();
343
344 for( int i = 0; i < finalPoints.PointCount(); ++i )
345 outline->Append( finalPoints.CPoint( i ) );
346
347 // In DEG45 mode, we may have intermediate points in the leader that should be
348 // included as they are shown in the preview. These typically maintain the
349 // 45 constraint
351 {
352 const auto& pts = aMgr.GetLeaderLinePoints();
353 for( int i = 1; i < pts.PointCount(); i++ )
354 outline->Append( pts.CPoint( i ) );
355 }
356
357 outline->Outline( 0 ).SetClosed( true );
358 outline->Outline( 0 ).Simplify( true );
359
360 // hand the zone over to the committer
361 commitZone( std::move( m_zone ) );
362 m_zone = nullptr;
363 }
364
366}
int color
Definition: DXF_plotter.cpp:57
virtual void Push(const wxString &aMessage=wxT("A commit"), 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.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:214
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:643
COMMIT & Remove(EDA_ITEM *aItem)
Notify observers that aItem has been removed.
Definition: commit.h:90
COMMIT & Add(EDA_ITEM *aItem)
Notify observers that aItem has been added.
Definition: commit.h:78
Tool responsible for drawing graphical elements like lines, arcs, circles, etc.
Definition: drawing_tool.h:51
PCB_BASE_EDIT_FRAME * m_frame
Definition: drawing_tool.h:342
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
void SetFilled(bool aFlag)
Definition: eda_shape.h:95
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: eda_shape.h:255
void SetShape(SHAPE_T aShape)
Definition: eda_shape.h:112
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)
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:316
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:346
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:1586
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1524
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:62
Common, abstract interface for edit frames.
const ZONE_SETTINGS & GetZoneSettings() const
BOARD * GetBoard() const
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
The selection tool: currently supports:
PCB_SELECTION & GetSelection()
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: pcb_shape.h:72
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 & GetLeaderLinePoints() const
Get the points comprising the leader line (the line from the last locked-in point to the current curs...
const std::deque< EDA_ITEM * > GetItems() const
Definition: selection.h:118
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:107
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
SHAPE_LINE_CHAIN & Outline(int aIndex)
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
int OutlineCount() const
Return the number of vertices in a given outline/hole.
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:143
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition: tool_base.h:184
T * getModel() const
Return the model object if it matches the requested type.
Definition: tool_base.h:196
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:287
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:70
void SetIsRuleArea(bool aEnable)
int m_NetcodeSelection
Definition: zone_settings.h:95
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
unsigned m_ZonePriority
Definition: zone_settings.h:81
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
SHAPE_POLY_SET * Outline()
Definition: zone.h:312
@ WHITE
Definition: color4d.h:48
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:59
@ 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:49
@ SIMILAR
Add a new zone with the same settings as an existing one.
@ CUTOUT
Make a cutout to an existing zone.
@ ADD
Add a new zone/keepout with fresh settings.
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