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 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*>( 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
233 m_tool.GetManager()->RunAction<EDA_ITEM*>( ACTIONS::selectItem, aZone.release() );
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:63
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: actions.h:220
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: actions.h:217
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:317
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:91
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition: commit.h:79
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:387
void SetFocus() override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:97
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:109
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:1675
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:1602
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:583
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:176
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:489
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.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Simplify(int aTolerance=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
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:88
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:99
Handle a list of polygons defining a copper zone.
Definition: zone.h:74
SHAPE_POLY_SET * Outline()
Definition: zone.h:335
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