KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 The 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#include <view/view_controls.h>
37
39 m_tool( aTool ),
40 m_params( aParams ),
41 m_parentView( *aTool.getView() )
42{
44}
45
46
48{
49 // remove the preview from the view
52}
53
54
56{
58 BOARD* board = frame->GetBoard();
59
60 // By default, new zones get the first unused priority
61 std::set<unsigned> priorities;
62
63 for( ZONE* zone : board->Zones() )
64 {
65 if( zone->GetTeardropAreaType() == TEARDROP_TYPE::TD_NONE
66 && ( zone->GetLayerSet() & LSET::AllCuMask() ).any()
67 && !zone->GetIsRuleArea() )
68 {
69 priorities.insert( zone->GetAssignedPriority() );
70 }
71 }
72
73 unsigned priority = 0;
74
75 for( unsigned exist_priority : priorities )
76 {
77 if( priority != exist_priority )
78 break;
79
80 ++priority;
81 }
82
83 aZoneInfo.m_ZonePriority = priority;
84}
85
86
87std::unique_ptr<ZONE> ZONE_CREATE_HELPER::createNewZone( bool aKeepout )
88{
90 BOARD* board = frame->GetBoard();
93 std::set<int> highlightedNets = board->GetHighLightNetCodes();
94
95 // Get the current default settings for zones
96 ZONE_SETTINGS zoneInfo = board->GetDesignSettings().GetDefaultZoneSettings();
97 zoneInfo.m_Layers.reset().set( m_params.m_layer ); // TODO(JE) multilayer defaults?
98 zoneInfo.m_layerProperties.clear(); // Do not copy over layer properties
99 zoneInfo.m_NetcodeSelection = highlightedNets.empty() ? -1 : *highlightedNets.begin();
100 zoneInfo.SetIsRuleArea( m_params.m_keepout );
101
102 if( m_params.m_mode != ZONE_MODE::GRAPHIC_POLYGON
103 && ( zoneInfo.m_Layers & LSET::AllCuMask() ).any() )
104 {
105 setUniquePriority( zoneInfo );
106 }
107
108 // If we don't have a net from highlighting, maybe we can get one from the selection
110
111 if( selectionTool && !selectionTool->GetSelection().Empty()
112 && zoneInfo.m_NetcodeSelection == -1 )
113 {
114 EDA_ITEM* item = *selectionTool->GetSelection().GetItems().begin();
115
116 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
117 zoneInfo.m_NetcodeSelection = bci->GetNetCode();
118 }
119
120 if( m_params.m_mode != ZONE_MODE::GRAPHIC_POLYGON )
121 {
122 // Show options dialog
123 int dialogResult;
124
125 if( m_params.m_keepout )
126 dialogResult = InvokeRuleAreaEditor( frame, &zoneInfo, m_tool.board() );
127 else if( ( zoneInfo.m_Layers & LSET::AllCuMask() ).any() )
128 dialogResult = InvokeCopperZonesEditor( frame, &zoneInfo );
129 else
130 dialogResult = InvokeNonCopperZonesEditor( frame, &zoneInfo );
131
132 if( dialogResult == wxID_CANCEL )
133 return nullptr;
134
135 controls->WarpMouseCursor( controls->GetCursorPosition(), true );
136 frame->GetCanvas()->SetFocus();
137 }
138
139 wxASSERT( !m_tool.m_isFootprintEditor || ( parent->Type() == PCB_FOOTPRINT_T ) );
140
141 std::unique_ptr<ZONE> newZone = std::make_unique<ZONE>( parent );
142
143 // Apply the selected settings
144 zoneInfo.ExportSetting( *newZone );
145
146 return newZone;
147}
148
149
150std::unique_ptr<ZONE> ZONE_CREATE_HELPER::createZoneFromExisting( const ZONE& aSrcZone )
151{
152 BOARD* board = m_tool.getModel<BOARD>();
153
154 std::unique_ptr<ZONE> newZone = std::make_unique<ZONE>( board );
155
156 ZONE_SETTINGS zoneSettings;
157 zoneSettings << aSrcZone;
158
159 zoneSettings.ExportSetting( *newZone );
160
161 return newZone;
162}
163
164
165void ZONE_CREATE_HELPER::performZoneCutout( ZONE& aZone, const ZONE& aCutout )
166{
167 BOARD_COMMIT commit( &m_tool );
168 std::vector<ZONE*> newZones;
169
170 // Clear the selection before removing the old zone
171 auto toolMgr = m_tool.GetManager();
173
174 SHAPE_POLY_SET originalOutline( *aZone.Outline() );
175 originalOutline.BooleanSubtract( *aCutout.Outline() );
176
177 // After substracting the hole, originalOutline can have more than one main outline.
178 // But a zone can have only one main outline, so create as many zones as originalOutline
179 // contains main outlines:
180 for( int outline = 0; outline < originalOutline.OutlineCount(); outline++ )
181 {
182 auto newZoneOutline = new SHAPE_POLY_SET;
183 newZoneOutline->AddOutline( originalOutline.Outline( outline ) );
184
185 // Add holes (if any) to the new zone outline:
186 for (int hole = 0; hole < originalOutline.HoleCount( outline ) ; hole++ )
187 newZoneOutline->AddHole( originalOutline.CHole( outline, hole ) );
188
189 auto newZone = new ZONE( aZone );
190 newZone->SetOutline( newZoneOutline );
191 newZone->SetLocalFlags( 1 );
192 newZone->HatchBorder();
193 newZone->UnFill();
194 newZones.push_back( newZone );
195 commit.Add( newZone );
196 }
197
198 commit.Remove( &aZone );
199 commit.Push( _( "Add Zone Cutout" ) );
200
201 // Select the new zone and set it as the source for the next cutout
202 if( newZones.empty() )
203 {
204 m_params.m_sourceZone = nullptr;
205 }
206 else
207 {
208 m_params.m_sourceZone = newZones[0];
209 toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, newZones[0] );
210 }
211}
212
213
214void ZONE_CREATE_HELPER::commitZone( std::unique_ptr<ZONE> aZone )
215{
216 switch ( m_params.m_mode )
217 {
218 case ZONE_MODE::CUTOUT:
219 // For cutouts, subtract from the source
221 break;
222
223 case ZONE_MODE::ADD:
224 case ZONE_MODE::SIMILAR:
225 {
226 BOARD_COMMIT commit( &m_tool );
227
228 aZone->HatchBorder();
229
230 commit.Add( aZone.get() );
231 commit.Push( _( "Draw Zone" ) );
232
234 break;
235 }
236
237 case ZONE_MODE::GRAPHIC_POLYGON:
238 {
239 BOARD_COMMIT commit( &m_tool );
240 BOARD* board = m_tool.getModel<BOARD>();
242 PCB_SHAPE* poly = new PCB_SHAPE( m_tool.m_frame->GetModel() );
243
244 poly->SetShape( SHAPE_T::POLY );
245 poly->SetFilled( layer != Edge_Cuts && layer != F_CrtYd && layer != B_CrtYd );
246
248 LINE_STYLE::SOLID ) );
249 poly->SetLayer( layer );
250 poly->SetPolyShape( *aZone->Outline() );
251
252 commit.Add( poly );
253 commit.Push( _( "Draw Polygon" ) );
254
256 break;
257 }
258 }
259}
260
261
263{
264 // if we don't have a zone, create one
265 if( !m_zone )
266 {
269 else
271
272 if( m_zone )
273 {
275
276 // set up properties from zone
277 const auto& settings = *m_parentView.GetPainter()->GetSettings();
278 COLOR4D color = settings.GetColor( nullptr, m_zone->GetFirstLayer() );
279
280 m_previewItem.SetStrokeColor( COLOR4D::WHITE );
281 m_previewItem.SetFillColor( color.WithAlpha( 0.2 ) );
282
284
287 }
288 }
289
290 return m_zone != nullptr;
291}
292
293
295{
296 // Handle a cancel-interactive
297 if( m_zone && !aMgr.IsPolygonInProgress() )
298 {
299 m_zone = nullptr;
301 return;
302 }
303
304 // send the points to the preview item
306 aMgr.GetLoopLinePoints() );
308}
309
310
312{
313 auto& finalPoints = aMgr.GetLockedInPoints();
314
315 if( finalPoints.PointCount() < 3 )
316 {
317 // just scrap the zone in progress
318 m_zone = nullptr;
319 }
320 else
321 {
322 // if m_params.m_mode == DRAWING_TOOL::ZONE_MODE::CUTOUT, m_zone will be merged to the
323 // existing zone as a new hole.
324 m_zone->Outline()->NewOutline();
325 auto* outline = m_zone->Outline();
326
327 for( int i = 0; i < finalPoints.PointCount(); ++i )
328 outline->Append( finalPoints.CPoint( i ) );
329
330 // In DEG45 mode, we may have intermediate points in the leader that should be included
331 // as they are shown in the preview. These typically maintain the 45 constraint
333 {
334 const SHAPE_LINE_CHAIN leaderPts = aMgr.GetLeaderLinePoints();
335 for( int i = 1; i < leaderPts.PointCount(); i++ )
336 outline->Append( leaderPts.CPoint( i ) );
337
338 const SHAPE_LINE_CHAIN loopPts = aMgr.GetLoopLinePoints();
339 for( int i = 1; i < loopPts.PointCount() - 1; i++ )
340 outline->Append( loopPts.CPoint( i ) );
341 }
342
343 SHAPE_LINE_CHAIN& chain = outline->Outline( 0 );
344
345 chain.SetClosed( true );
346 chain.Simplify( true );
347
348 // Remove the start point if it lies on the line between neighbouring points.
349 // Simplify doesn't handle that currently.
350 if( chain.PointCount() >= 3 )
351 {
352 SEG seg( chain.CPoint( -1 ), chain.CPoint( 1 ) );
353
354 if( seg.LineDistance( chain.CPoint( 0 ) ) <= 1 )
355 chain.Remove( 0 );
356 }
357
358 // hand the zone over to the committer
359 commitZone( std::move( m_zone ) );
360 m_zone = nullptr;
361 }
362
364}
int color
Definition: DXF_plotter.cpp:60
BASE_SET & reset(size_t pos)
Definition: base_set.h:143
BASE_SET & set(size_t pos)
Definition: base_set.h:116
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
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:297
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:946
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition: commit.h:92
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
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:396
void SetFocus() override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:95
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:107
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: eda_shape.h:345
virtual void SetFilled(bool aFlag)
Definition: eda_shape.h:136
void SetShape(SHAPE_T aShape)
Definition: eda_shape.h:167
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:297
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:332
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:1673
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:216
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1600
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:572
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:69
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:72
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:179
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: pcb_shape.h:92
virtual bool Is45Limited() const
Should the tool use its 45° mode option?
BOARD * board() const
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:428
const std::deque< EDA_ITEM * > GetItems() const
Definition: selection.h:121
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:110
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.
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.
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
Simple container to manage line stroke parameters.
Definition: stroke_params.h:94
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:146
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:150
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:397
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:87
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_layerProperties
void SetIsRuleArea(bool aEnable)
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
unsigned m_ZonePriority
Definition: zone_settings.h:98
Handle a list of polygons defining a copper zone.
Definition: zone.h:74
SHAPE_POLY_SET * Outline()
Definition: zone.h:368
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, BOARD *aBoard, 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:116
@ Edge_Cuts
Definition: layer_ids.h:112
@ B_CrtYd
Definition: layer_ids.h:115
@ GEOMETRY
Position or shape has changed.
Definition: view_item.h:55
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.
const SHAPE_LINE_CHAIN chain
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86