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 <fp_shape.h>
31 #include <board_commit.h>
32 #include <pcb_painter.h>
33 #include <tools/pcb_actions.h>
35 #include <zone_filler.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 
54 std::unique_ptr<ZONE> ZONE_CREATE_HELPER::createNewZone( bool aKeepout )
55 {
57  BOARD* board = frame->GetBoard();
60  std::set<int> highlightedNets = board->GetHighLightNetCodes();
61 
62  // Get the current default settings for zones
63  ZONE_SETTINGS zoneInfo = frame->GetZoneSettings();
64  zoneInfo.m_Layers.reset().set( m_params.m_layer ); // TODO(JE) multilayer defaults?
65  zoneInfo.m_NetcodeSelection = highlightedNets.empty() ? -1 : *highlightedNets.begin();
66  zoneInfo.SetIsRuleArea( m_params.m_keepout );
68 
69  // If we don't have a net from highlighing, maybe we can get one from the selection
71 
72  if( selectionTool && !selectionTool->GetSelection().Empty()
73  && zoneInfo.m_NetcodeSelection == -1 )
74  {
75  EDA_ITEM* item = *selectionTool->GetSelection().GetItems().begin();
76 
77  if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
78  zoneInfo.m_NetcodeSelection = bci->GetNetCode();
79  }
80 
82  {
83  // Get the current default settings for zones
84 
85  // Show options dialog
86  int dialogResult;
87 
88  if( m_params.m_keepout )
89  dialogResult = InvokeRuleAreaEditor( frame, &zoneInfo );
90  else
91  {
92  // TODO(JE) combine these dialogs?
93  if( ( zoneInfo.m_Layers & LSET::AllCuMask() ).any() )
94  dialogResult = InvokeCopperZonesEditor( frame, &zoneInfo );
95  else
96  dialogResult = InvokeNonCopperZonesEditor( frame, &zoneInfo );
97  }
98 
99  if( dialogResult == wxID_CANCEL )
100  return nullptr;
101 
102  controls->WarpCursor( controls->GetCursorPosition(), true );
103  }
104 
105  // The new zone is a ZONE if created in the board editor and a FP_ZONE if created in the
106  // footprint editor
107  wxASSERT( !m_tool.m_isFootprintEditor || ( parent->Type() == PCB_FOOTPRINT_T ) );
108 
109  std::unique_ptr<ZONE> newZone = m_tool.m_isFootprintEditor ?
110  std::make_unique<FP_ZONE>( parent ) :
111  std::make_unique<ZONE>( parent );
112 
113  // Apply the selected settings
114  zoneInfo.ExportSetting( *newZone );
115 
116  return newZone;
117 }
118 
119 
120 std::unique_ptr<ZONE> ZONE_CREATE_HELPER::createZoneFromExisting( const ZONE& aSrcZone )
121 {
122  BOARD* board = m_tool.getModel<BOARD>();
123 
124  std::unique_ptr<ZONE> newZone = std::make_unique<ZONE>( board );
125 
126  ZONE_SETTINGS zoneSettings;
127  zoneSettings << aSrcZone;
128 
129  zoneSettings.ExportSetting( *newZone );
130 
131  return newZone;
132 }
133 
134 
136 {
137  BOARD_COMMIT commit( &m_tool );
138  BOARD* board = m_tool.getModel<BOARD>();
139  std::vector<ZONE*> newZones;
140 
141  // Clear the selection before removing the old zone
142  auto toolMgr = m_tool.GetManager();
143  toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
144 
145  SHAPE_POLY_SET originalOutline( *aZone.Outline() );
146  originalOutline.BooleanSubtract( *aCutout.Outline(), SHAPE_POLY_SET::PM_FAST );
147 
148  // After substracting the hole, originalOutline can have more than one
149  // main outline.
150  // But a zone can have only one main outline, so create as many zones as
151  // originalOutline contains main outlines:
152  for( int outline = 0; outline < originalOutline.OutlineCount(); outline++ )
153  {
154  auto newZoneOutline = new SHAPE_POLY_SET;
155  newZoneOutline->AddOutline( originalOutline.Outline( outline ) );
156 
157  // Add holes (if any) to thez new zone outline:
158  for (int hole = 0; hole < originalOutline.HoleCount( outline ) ; hole++ )
159  newZoneOutline->AddHole( originalOutline.CHole( outline, hole ) );
160 
161  auto newZone = new ZONE( aZone );
162  newZone->SetOutline( newZoneOutline );
163  newZone->SetLocalFlags( 1 );
164  newZone->HatchBorder();
165  newZones.push_back( newZone );
166  commit.Add( newZone );
167  }
168 
169  commit.Remove( &aZone );
170 
171  ZONE_FILLER filler( board, &commit );
172 
173  std::lock_guard<KISPINLOCK> lock( board->GetConnectivity()->GetLock() );
174 
175  if( !filler.Fill( newZones ) )
176  {
177  commit.Revert();
178  return;
179  }
180 
181  commit.Push( _( "Add a zone cutout" ) );
182 
183  // Select the new zone and set it as the source for the next cutout
184  if( newZones.empty() )
185  {
186  m_params.m_sourceZone = nullptr;
187  }
188  else
189  {
190  m_params.m_sourceZone = newZones[0];
191  toolMgr->RunAction( PCB_ACTIONS::selectItem, true, newZones[0] );
192  }
193 
194 }
195 
196 
197 void ZONE_CREATE_HELPER::commitZone( std::unique_ptr<ZONE> aZone )
198 {
199  switch ( m_params.m_mode )
200  {
201  case ZONE_MODE::CUTOUT:
202  // For cutouts, subtract from the source
204  break;
205 
206  case ZONE_MODE::ADD:
207  case ZONE_MODE::SIMILAR:
208  {
209  BOARD_COMMIT bCommit( &m_tool );
210 
211  aZone->HatchBorder();
212  bCommit.Add( aZone.get() );
213 
214  BOARD* board = m_tool.getModel<BOARD>();
215  std::lock_guard<KISPINLOCK> lock( board->GetConnectivity()->GetLock() );
216 
217  if( !m_params.m_keepout )
218  {
219  ZONE_FILLER filler( board, &bCommit );
220  std::vector<ZONE*> toFill = { aZone.get() };
221 
222  if( !filler.Fill( toFill ) )
223  {
224  bCommit.Revert();
225  break;
226  }
227  }
228 
229  bCommit.Push( _( "Add a zone" ) );
230  m_tool.GetManager()->RunAction( PCB_ACTIONS::selectItem, true, aZone.release() );
231  break;
232  }
233 
235  {
236  BOARD_COMMIT bCommit( &m_tool );
238  LSET graphicPolygonsLayers = LSET::AllLayersMask();
239 
240  graphicPolygonsLayers.reset( Edge_Cuts ).reset( F_CrtYd ).reset( B_CrtYd );
241 
242  auto poly = m_tool.m_isFootprintEditor ? new FP_SHAPE( (FOOTPRINT*) parent )
243  : new PCB_SHAPE();
244  poly->SetShape( S_POLYGON );
245  poly->SetFilled( graphicPolygonsLayers.Contains( m_params.m_layer ) );
246  poly->SetLayer( m_params.m_layer );
247  poly->SetPolyShape( *aZone->Outline() );
248  bCommit.Add( poly );
250 
251  bCommit.Push( _( "Add a graphical polygon" ) );
252 
253  break;
254  }
255  }
256 }
257 
258 
260 {
261  // if we don't have a zone, create one
262  // the user's choice here can affect things like the colour of the preview
263  if( !m_zone )
264  {
265  if( m_params.m_sourceZone )
267  else
269 
270  if( m_zone )
271  {
273 
274  // set up poperties from zone
275  const auto& settings = *m_parentView.GetPainter()->GetSettings();
276  COLOR4D color = settings.GetColor( nullptr, m_zone->GetLayer() );
277 
279  m_previewItem.SetFillColor( color.WithAlpha( 0.2 ) );
280 
282 
285  }
286  }
287 
288  return m_zone != nullptr;
289 }
290 
291 
293 {
294  // send the points to the preview item
297 }
298 
299 
301 {
302  auto& finalPoints = aMgr.GetLockedInPoints();
303 
304  if( finalPoints.PointCount() < 3 )
305  {
306  // just scrap the zone in progress
307  m_zone = nullptr;
308  }
309  else
310  {
311  // if m_params.m_mode == DRAWING_TOOL::ZONE_MODE::CUTOUT, m_zone
312  // will be merged to the existing zone as a new hole.
313  m_zone->Outline()->NewOutline();
314  auto* outline = m_zone->Outline();
315 
316  for( int i = 0; i < finalPoints.PointCount(); ++i )
317  outline->Append( finalPoints.CPoint( i ) );
318 
319  // In DEG45 mode, we may have intermediate points in the leader that should be
320  // included as they are shown in the preview. These typically maintain the
321  // 45 constraint
323  {
324  const auto& pts = aMgr.GetLeaderLinePoints();
325  for( int i = 1; i < pts.PointCount(); i++ )
326  outline->Append( pts.CPoint( i ) );
327  }
328 
329  outline->Outline( 0 ).SetClosed( true );
330  outline->RemoveNullSegments();
331  outline->Simplify( SHAPE_POLY_SET::PM_FAST );
332 
333  // hand the zone over to the committer
334  commitZone( std::move( m_zone ) );
335  m_zone = nullptr;
336  }
337 
339 }
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:63
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
void OnComplete(const POLYGON_GEOM_MANAGER &aMgr) override
Add a new zone with the same settings as an existing one.
T * getModel() const
Return the model object if it matches the requested type.
Definition: tool_base.h:197
ZONE * m_sourceZone
Zone leader mode.
void SetStrokeColor(const COLOR4D &aNewColor)
Set the fill color to set before drawing preview.
COMMIT & Add(EDA_ITEM *aItem)
Notify observers that aItem has been added.
Definition: commit.h:78
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...
int InvokeNonCopperZonesEditor(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings)
Function InvokeNonCopperZonesEditor invokes up a modal dialog window for non-copper zone editing.
SHAPE_POLY_SET * Outline()
Definition: zone.h:323
virtual void Revert() override
ZONE_CREATE_HELPER(DRAWING_TOOL &aTool, PARAMS &aParams)
bool Contains(PCB_LAYER_ID aLayer)
See if the layer set contains a PCB layer.
int color
Definition: DXF_plotter.cpp:60
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:351
DRAWING_TOOL & m_tool
Parameters of the zone to be drawn.
polygon (not yet used for tracks, but could be in microwave apps)
Definition: board_item.h:54
void performZoneCutout(ZONE &aZone, ZONE &aCutout)
Cut one zone out of another one (i.e.
PCB_LAYER_ID m_layer
The zone mode to operate in.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:141
KIGFX::PREVIEW::POLYGON_ITEM m_previewItem
view that show the preview item
Parameters used to fully describe a zone creation process.
void SetLeaderMode(LEADER_MODE aMode)
Set the leader mode to use when calculating the leader/returner lines.
LEADER_MODE GetLeaderMode() const
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:207
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:144
int m_NetcodeSelection
Definition: zone_settings.h:93
PCB_SELECTION & GetSelection()
Return the set of currently selected items.
bool Fill(std::vector< ZONE * > &aZones, bool aCheck=false, wxWindow *aParent=nullptr)
Fills the given list of zones.
Definition: zone_filler.cpp:85
virtual void WarpCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
If enabled (.
LSET is a set of PCB_LAYER_IDs.
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
Tool responsible for drawing graphical elements like lines, arcs, circles, etc.
Definition: drawing_tool.h:50
Represent a set of closed polygons.
const ZONE_SETTINGS & GetZoneSettings() const
KIGFX::VIEW & m_parentView
The zone-in-progress.
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:414
const std::deque< EDA_ITEM * > GetItems() const
Definition: selection.h:133
An interface for classes handling user events controlling the view behavior such as zooming,...
Add a new zone/keepout with fresh settings.
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...
static LSET AllLayersMask()
Definition: lset.cpp:787
void commitZone(std::unique_ptr< ZONE > aZone)
Commit the current zone-in-progress to the BOARD.
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
COMMIT & Remove(EDA_ITEM *aItem)
Notify observers that aItem has been removed.
Definition: commit.h:90
Unconstrained point-to-point.
void SetFillColor(const COLOR4D &aNewColor)
Set the line width to set before drawing preview.
void SetIsRuleArea(bool aEnable)
bool m_isFootprintEditor
int InvokeRuleAreaEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings)
Function InvokeRuleAreaEditor invokes up a modal dialog window for copper zone editing.
Make a cutout to an existing zone.
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:122
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
PCB_BASE_EDIT_FRAME * m_frame
Definition: drawing_tool.h:232
ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:67
PARAMS & m_params
The preview item to display.
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
Definition: color4d.h:48
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:291
void OnGeometryChange(const POLYGON_GEOM_MANAGER &aMgr) override
Called when the polygon is complete.
std::unique_ptr< ZONE > createZoneFromExisting(const ZONE &aSrcZone)
Create a new zone with the settings from an existing zone.
std::unique_ptr< ZONE > m_zone
Common, abstract interface for edit frames.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
#define _(s)
Definition: 3d_actions.cpp:33
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:66
The selection tool: currently supports:
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:149
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Revert the commit by restoring the modified items state.
void SetPoints(const SHAPE_LINE_CHAIN &aLockedInPts, const SHAPE_LINE_CHAIN &aLeaderPts)
Set the polygon points.
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition: tool_base.h:185
int InvokeCopperZonesEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings)
Function InvokeCopperZonesEditor invokes up a modal dialog window for copper zone editing.
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1454
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:321
const SHAPE_LINE_CHAIN & GetLockedInPoints() const
Get the "locked-in" points that describe the polygon itself.
std::unique_ptr< ZONE > createNewZone(bool aKeepout)
Prompt the user for new zone settings, and create a new zone with those settings.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
Abstract interface for BOARD_ITEMs capable of storing other items inside.
BOARD * GetBoard() const
POLYGON_GEOM_MANAGER::LEADER_MODE m_leaderMode
bool m_keepout
< Should create a keepout zone?
Class that handles the drawing of a polygon, including management of last corner deletion and drawing...
ZONE_MODE m_mode
Zone settings source (for similar and cutout zones)
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
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:1508
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
Position or shape has changed.
Definition: view_item.h:54
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98