KiCad PCB EDA Suite
point_editor.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) 2013-2019 CERN
5  * @author Maciej Suminski <maciej.suminski@cern.ch>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <functional>
26 using namespace std::placeholders;
27 
28 #include <tool/tool_manager.h>
29 #include <view/view_controls.h>
31 #include <geometry/seg.h>
32 #include <confirm.h>
33 
34 #include "pcb_actions.h"
35 #include "selection_tool.h"
36 #include "point_editor.h"
37 #include "grid_helper.h"
38 #include <board_commit.h>
39 #include <bitmaps.h>
40 #include <status_popup.h>
41 
42 #include <pcb_edit_frame.h>
43 #include <class_edge_mod.h>
44 #include <class_dimension.h>
45 #include <class_zone.h>
46 #include <class_board.h>
47 #include <class_module.h>
50 
51 #include "zone_filler.h"
52 
53 // Point editor
54 TOOL_ACTION PCB_ACTIONS::pointEditorAddCorner( "pcbnew.PointEditor.addCorner",
55  AS_GLOBAL, WXK_INSERT,
56  _( "Create Corner" ), _( "Create a corner" ), add_corner_xpm );
57 
58 TOOL_ACTION PCB_ACTIONS::pointEditorRemoveCorner( "pcbnew.PointEditor.removeCorner",
59  AS_GLOBAL, 0,
60  _( "Remove Corner" ), _( "Remove corner" ), delete_xpm );
61 
62 
63 // Few constants to avoid using bare numbers for point indices
65 {
67 };
68 
70 {
72 };
73 
75 {
77 };
78 
80 {
85 };
86 
88 {
93 };
94 
96 {
97 private:
98 
99  static void buildForPolyOutline( std::shared_ptr<EDIT_POINTS> points,
100  const SHAPE_POLY_SET* aOutline, KIGFX::GAL* aGal )
101  {
102 
103  int cornersCount = aOutline->TotalVertices();
104 
105  for( auto iterator = aOutline->CIterateWithHoles(); iterator; iterator++ )
106  {
107  points->AddPoint( *iterator );
108 
109  if( iterator.IsEndContour() )
110  points->AddBreak();
111  }
112 
113  // Lines have to be added after creating edit points,
114  // as they use EDIT_POINT references
115  for( int i = 0; i < cornersCount - 1; ++i )
116  {
117  if( points->IsContourEnd( i ) )
118  {
119  points->AddLine( points->Point( i ),
120  points->Point( points->GetContourStartIdx( i ) ) );
121  }
122  else
123  {
124  points->AddLine( points->Point( i ), points->Point( i + 1 ) );
125  }
126 
127  points->Line( i ).SetConstraint( new EC_SNAPLINE( points->Line( i ),
128  std::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) );
129  }
130 
131  // The last missing line, connecting the last and the first polygon point
132  points->AddLine( points->Point( cornersCount - 1 ),
133  points->Point( points->GetContourStartIdx( cornersCount - 1 ) ) );
134 
135  points->Line( points->LinesSize() - 1 ).SetConstraint(
136  new EC_SNAPLINE( points->Line( points->LinesSize() - 1 ),
137  std::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) );
138  }
139 
140 public:
141  static std::shared_ptr<EDIT_POINTS> Make( EDA_ITEM* aItem, KIGFX::GAL* aGal )
142  {
143  std::shared_ptr<EDIT_POINTS> points = std::make_shared<EDIT_POINTS>( aItem );
144 
145  if( !aItem )
146  return points;
147 
148  // Generate list of edit points basing on the item type
149  switch( aItem->Type() )
150  {
151  case PCB_LINE_T:
152  case PCB_MODULE_EDGE_T:
153  {
154  const DRAWSEGMENT* segment = static_cast<const DRAWSEGMENT*>( aItem );
155 
156  switch( segment->GetShape() )
157  {
158  case S_SEGMENT:
159  points->AddPoint( segment->GetStart() );
160  points->AddPoint( segment->GetEnd() );
161  break;
162 
163  case S_ARC:
164  points->AddPoint( segment->GetCenter() );
165  points->AddPoint( segment->GetArcStart() );
166  points->AddPoint( segment->GetArcMid() );
167  points->AddPoint( segment->GetArcEnd() );
168 
169  // Set constraints
170  // Arc end has to stay at the same radius as the start
171  points->Point( ARC_END ).SetConstraint( new EC_CIRCLE( points->Point( ARC_END ),
172  points->Point( ARC_CENTER ),
173  points->Point( ARC_START ) ) );
174 
175  points->Point( ARC_MID ).SetConstraint( new EC_LINE( points->Point( ARC_MID ),
176  points->Point( ARC_CENTER ) ) );
177  break;
178 
179  case S_CIRCLE:
180  points->AddPoint( segment->GetCenter() );
181  points->AddPoint( segment->GetEnd() );
182 
183  break;
184 
185  case S_POLYGON:
186  buildForPolyOutline( points, &segment->GetPolyShape(), aGal );
187  break;
188 
189  case S_CURVE:
190  points->AddPoint( segment->GetStart() );
191  points->AddPoint( segment->GetBezControl1() );
192  points->AddPoint( segment->GetBezControl2() );
193  points->AddPoint( segment->GetEnd() );
194  break;
195 
196  default: // suppress warnings
197  break;
198  }
199 
200  break;
201  }
202 
203  case PCB_ZONE_AREA_T:
204  {
205  auto zone = static_cast<const ZONE_CONTAINER*>( aItem );
206  buildForPolyOutline( points, zone->Outline(), aGal );
207  break;
208  }
209 
210  case PCB_DIMENSION_T:
211  {
212  const DIMENSION* dimension = static_cast<const DIMENSION*>( aItem );
213 
214  points->AddPoint( dimension->m_crossBarO );
215  points->AddPoint( dimension->m_crossBarF );
216  points->AddPoint( dimension->m_featureLineGO );
217  points->AddPoint( dimension->m_featureLineDO );
218 
219  // Dimension height setting - edit points should move only along the feature lines
220  points->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARO ),
221  points->Point( DIM_FEATUREGO ) ) );
222  points->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARF ),
223  points->Point( DIM_FEATUREDO ) ) );
224 
225  break;
226  }
227 
228  default:
229  points.reset();
230  break;
231  }
232 
233  return points;
234  }
235 
236 private:
238 };
239 
240 
242  PCB_TOOL_BASE( "pcbnew.PointEditor" ),
243  m_selectionTool( NULL ),
244  m_editedPoint( NULL ),
245  m_original( VECTOR2I( 0, 0 ) ),
246  m_altConstrainer( VECTOR2I( 0, 0 ) ),
247  m_refill( false )
248 {
249 }
250 
251 
253 {
254  m_refill = false;
255  m_editPoints.reset();
256  m_altConstraint.reset();
257  getViewControls()->SetAutoPan( false );
258 
259  m_statusPopup.reset( new STATUS_TEXT_POPUP( getEditFrame<PCB_BASE_EDIT_FRAME>() ) );
260  m_statusPopup->SetTextColor( wxColour( 255, 0, 0 ) );
261  m_statusPopup->SetText( _( "Self-intersecting polygons are not allowed" ) );
262 }
263 
264 
266 {
267  // Find the selection tool, so they can cooperate
269 
270  wxASSERT_MSG( m_selectionTool, _( "pcbnew.InteractiveSelection tool is not available" ) );
271 
272  auto& menu = m_selectionTool->GetToolMenu().GetMenu();
275  std::bind( &POINT_EDITOR::removeCornerCondition, this, _1 ) );
276 
277  return true;
278 }
279 
280 
282 {
283  EDIT_POINT* point = m_editedPoint;
284 
285  if( aEvent.IsMotion() )
286  {
287  point = m_editPoints->FindPoint( aEvent.Position(), getView() );
288  }
289  else if( aEvent.IsDrag( BUT_LEFT ) )
290  {
291  point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
292  }
293 
294  if( m_editedPoint != point )
295  setEditedPoint( point );
296 }
297 
298 
300 {
301  if( !m_selectionTool )
302  return 0;
303 
305 
306  if( selection.Size() != 1 )
307  return 0;
308 
309  Activate();
310 
312  KIGFX::VIEW* view = getView();
313  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
314 
315  controls->ShowCursor( true );
316 
317  GRID_HELPER grid( editFrame );
318  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
319 
320  m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() );
321 
322  if( !m_editPoints )
323  return 0;
324 
325  view->Add( m_editPoints.get() );
326  setEditedPoint( nullptr );
327  m_refill = false;
328  bool modified = false;
329  bool revert = false;
330 
331  BOARD_COMMIT commit( editFrame );
332  LSET snapLayers = item->GetLayerSet();
333 
334  if( item->Type() == PCB_DIMENSION_T )
335  snapLayers = LSET::AllLayersMask();
336 
337  // Main loop: keep receiving events
338  while( OPT_TOOL_EVENT evt = Wait() )
339  {
340  if( revert )
341  break;
342 
343  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
344  grid.SetUseGrid( !evt->Modifier( MD_ALT ) );
345  controls->SetSnapping( !evt->Modifier( MD_ALT ) );
346 
347  if( !m_editPoints ||
348  evt->Matches( EVENTS::ClearedEvent ) ||
349  evt->Matches( EVENTS::UnselectedEvent ) ||
350  evt->Matches( EVENTS::SelectedEvent ) )
351  {
352  break;
353  }
354 
355  if ( !modified )
356  updateEditedPoint( *evt );
357 
358  if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
359  {
360  if( !modified )
361  {
362  commit.StageItems( selection, CHT_MODIFY );
363 
364  controls->ForceCursorPosition( false );
365  m_original = *m_editedPoint; // Save the original position
366  controls->SetAutoPan( true );
367  modified = true;
368  grid.SetAuxAxes( true, m_original.GetPosition(), true );
369  }
370 
371  //TODO: unify the constraints to solve simultaneously instead of sequentially
372  m_editedPoint->SetPosition( grid.BestSnapAnchor( evt->Position(),
373  snapLayers, { item } ) );
374  bool enableAltConstraint = !!evt->Modifier( MD_CTRL );
375 
376  if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint
377  setAltConstraint( enableAltConstraint );
378 
379  if( m_altConstraint )
380  m_altConstraint->Apply();
381  else
383 
385  snapLayers, { item } ) );
386 
387  updateItem();
388  updatePoints();
389  }
390 
391  else if( evt->IsMouseUp( BUT_LEFT ) )
392  {
393  controls->SetAutoPan( false );
394  setAltConstraint( false );
395 
396  if( modified )
397  {
398  commit.Push( _( "Drag a corner" ) );
399  modified = false;
400  m_refill = true;
401  }
402 
403  m_toolMgr->PassEvent();
404  }
405 
406  else if( evt->IsCancel() )
407  {
408  if( modified ) // Restore the last change
409  revert = true;
410 
411  // Let the selection tool receive the event too
412  m_toolMgr->PassEvent();
413 
414  // Do not exit right now, let the selection clear the selection
415  //break;
416  }
417 
418  else
419  {
420  m_toolMgr->PassEvent();
421  }
422  }
423 
424  if( m_editPoints )
425  {
426  view->Remove( m_editPoints.get() );
427 
428  if( modified && revert )
429  commit.Revert();
430 
431  finishItem();
432  m_editPoints.reset();
433  }
434 
435  frame()->UpdateMsgPanel();
436 
437  return 0;
438 }
439 
440 
442 {
443  EDA_ITEM* item = m_editPoints->GetParent();
444 
445  if( !item )
446  return;
447 
448  switch( item->Type() )
449  {
450  case PCB_LINE_T:
451  case PCB_MODULE_EDGE_T:
452  {
453  DRAWSEGMENT* segment = static_cast<DRAWSEGMENT*>( item );
454  switch( segment->GetShape() )
455  {
456  case S_SEGMENT:
457  if( isModified( m_editPoints->Point( SEG_START ) ) )
458  segment->SetStart( wxPoint( m_editPoints->Point( SEG_START ).GetPosition().x,
459  m_editPoints->Point( SEG_START ).GetPosition().y ) );
460 
461  else if( isModified( m_editPoints->Point( SEG_END ) ) )
462  segment->SetEnd( wxPoint( m_editPoints->Point( SEG_END ).GetPosition().x,
463  m_editPoints->Point( SEG_END ).GetPosition().y ) );
464 
465  break;
466 
467  case S_ARC:
468  {
469  VECTOR2I center = m_editPoints->Point( ARC_CENTER ).GetPosition();
470  VECTOR2I mid = m_editPoints->Point( ARC_MID ).GetPosition();
471  VECTOR2I start = m_editPoints->Point( ARC_START ).GetPosition();
472  VECTOR2I end = m_editPoints->Point( ARC_END ).GetPosition();
473 
474  if( center != segment->GetCenter() )
475  {
476  wxPoint moveVector = wxPoint( center.x, center.y ) - segment->GetCenter();
477  segment->Move( moveVector );
478 
479  m_editPoints->Point( ARC_START ).SetPosition( segment->GetArcStart() );
480  m_editPoints->Point( ARC_END ).SetPosition( segment->GetArcEnd() );
481  m_editPoints->Point( ARC_MID ).SetPosition( segment->GetArcMid() );
482  }
483  else
484  {
485  if( mid != segment->GetArcMid() )
486  {
487  center = GetArcCenter( start, mid, end );
488  segment->SetCenter( wxPoint( center.x, center.y ) );
489  m_editPoints->Point( ARC_CENTER ).SetPosition( center );
490  }
491 
492  segment->SetArcStart( wxPoint( start.x, start.y ) );
493 
494  VECTOR2D startLine = start - center;
495  VECTOR2D endLine = end - center;
496  double newAngle = RAD2DECIDEG( endLine.Angle() - startLine.Angle() );
497 
498  // Adjust the new angle to (counter)clockwise setting
499  bool clockwise = ( segment->GetAngle() > 0 );
500 
501  if( clockwise && newAngle < 0.0 )
502  newAngle += 3600.0;
503  else if( !clockwise && newAngle > 0.0 )
504  newAngle -= 3600.0;
505 
506  segment->SetAngle( newAngle );
507  }
508 
509  break;
510  }
511 
512  case S_CIRCLE:
513  {
514  const VECTOR2I& center = m_editPoints->Point( CIRC_CENTER ).GetPosition();
515  const VECTOR2I& end = m_editPoints->Point( CIRC_END ).GetPosition();
516 
517  if( isModified( m_editPoints->Point( CIRC_CENTER ) ) )
518  {
519  wxPoint moveVector = wxPoint( center.x, center.y ) - segment->GetCenter();
520  segment->Move( moveVector );
521  }
522  else
523  {
524  segment->SetEnd( wxPoint( end.x, end.y ) );
525  }
526 
527  break;
528  }
529 
530  case S_POLYGON:
531  {
532  SHAPE_POLY_SET& outline = segment->GetPolyShape();
533 
534  for( int i = 0; i < outline.TotalVertices(); ++i )
535  outline.Vertex( i ) = m_editPoints->Point( i ).GetPosition();
536 
537  validatePolygon( outline );
538  break;
539  }
540 
541  case S_CURVE:
542  if( isModified( m_editPoints->Point( BEZIER_CURVE_START ) ) )
543  segment->SetStart( wxPoint( m_editPoints->Point( BEZIER_CURVE_START ).GetPosition().x,
544  m_editPoints->Point( BEZIER_CURVE_START ).GetPosition().y ) );
545  else if( isModified( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ) ) )
546  segment->SetBezControl1( wxPoint( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ).GetPosition().x,
547  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ).GetPosition().y ) );
548  else if( isModified( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ) ) )
549  segment->SetBezControl2( wxPoint( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ).GetPosition().x,
550  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ).GetPosition().y ) );
551  else if( isModified( m_editPoints->Point( BEZIER_CURVE_END ) ) )
552  segment->SetEnd( wxPoint( m_editPoints->Point( BEZIER_CURVE_END ).GetPosition().x,
553  m_editPoints->Point( BEZIER_CURVE_END ).GetPosition().y ) );
554 
555  segment->RebuildBezierToSegmentsPointsList( segment->GetWidth() );
556  break;
557 
558  default: // suppress warnings
559  break;
560  }
561 
562  // Update relative coordinates for module edges
563  if( EDGE_MODULE* edge = dyn_cast<EDGE_MODULE*>( item ) )
564  edge->SetLocalCoord();
565 
566  break;
567  }
568 
569  case PCB_ZONE_AREA_T:
570  {
571  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
572  zone->ClearFilledPolysList();
573  SHAPE_POLY_SET& outline = *zone->Outline();
574 
575  for( int i = 0; i < outline.TotalVertices(); ++i )
576  {
577  if( outline.Vertex( i ) != m_editPoints->Point( i ).GetPosition() )
578  zone->SetNeedRefill( true );
579 
580  outline.Vertex( i ) = m_editPoints->Point( i ).GetPosition();
581  }
582 
583  validatePolygon( outline );
584  zone->Hatch();
585  break;
586  }
587 
588  case PCB_DIMENSION_T:
589  {
590  DIMENSION* dimension = static_cast<DIMENSION*>( item );
591 
592  // Check which point is currently modified and updated dimension's points respectively
593  if( isModified( m_editPoints->Point( DIM_CROSSBARO ) ) )
594  {
595  VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetOrigin() );
596  VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );
597 
598  if( featureLine.Cross( crossBar ) > 0 )
599  dimension->SetHeight( -featureLine.EuclideanNorm() );
600  else
601  dimension->SetHeight( featureLine.EuclideanNorm() );
602  }
603 
604  else if( isModified( m_editPoints->Point( DIM_CROSSBARF ) ) )
605  {
606  VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetEnd() );
607  VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );
608 
609  if( featureLine.Cross( crossBar ) > 0 )
610  dimension->SetHeight( -featureLine.EuclideanNorm() );
611  else
612  dimension->SetHeight( featureLine.EuclideanNorm() );
613  }
614 
615  else if( isModified( m_editPoints->Point( DIM_FEATUREGO ) ) )
616  {
617  dimension->SetOrigin( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ) );
618  m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
619  m_editPoints->Point( DIM_FEATUREGO ) ) );
620  m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
621  m_editPoints->Point( DIM_FEATUREDO ) ) );
622  }
623 
624  else if( isModified( m_editPoints->Point( DIM_FEATUREDO ) ) )
625  {
626  dimension->SetEnd( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ) );
627  m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
628  m_editPoints->Point( DIM_FEATUREGO ) ) );
629  m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
630  m_editPoints->Point( DIM_FEATUREDO ) ) );
631  }
632 
633  break;
634  }
635 
636  default:
637  break;
638  }
639 
640  if( frame() )
641  frame()->SetMsgPanel( item );
642 }
643 
644 
646 {
647  auto item = m_editPoints->GetParent();
648 
649  if( !item )
650  return;
651 
652  if( item->Type() == PCB_ZONE_AREA_T )
653  {
654  auto zone = static_cast<ZONE_CONTAINER*>( item );
655 
656  if( zone->IsFilled() && m_refill && zone->NeedRefill() )
657  {
658  ZONE_FILLER filler( board() );
659  // A progress reporter can be usefull. However it works fine only on Windows
660  // so enable it only on Windows.
661  // On Linux, the filled areas are incorrectly shown: the insulated islands
662  // remain displayed, although they are removed from the actual filled areas list
663  //
664  // Fix me: try to make it working on Linux.
665  //
666  #ifdef __WINDOWS__
667  WX_PROGRESS_REPORTER reporter( getEditFrame<PCB_BASE_FRAME>(), _( "Refill Zones" ), 4 );
668  filler.SetProgressReporter( &reporter );
669  #endif
670  filler.Fill( { zone } );
671  }
672  }
673 }
674 
675 
676 bool POINT_EDITOR::validatePolygon( SHAPE_POLY_SET& aModified, const SHAPE_POLY_SET* aOriginal ) const
677 {
678  if( !aModified.IsSelfIntersecting() )
679  {
680  m_statusPopup->Hide();
681  return true;
682  }
683 
684  if( m_statusPopup )
685  {
686  wxPoint p = wxGetMousePosition() + wxPoint( 20, 20 );
687  m_statusPopup->Move( p );
688  m_statusPopup->Popup( getEditFrame<PCB_BASE_FRAME>() );
689  m_statusPopup->Expire( 1500 );
690  }
691 
692  if( aOriginal )
693  aModified = *aOriginal;
694 
695  return false;
696 }
697 
698 
700 {
701  if( !m_editPoints )
702  return;
703 
704  EDA_ITEM* item = m_editPoints->GetParent();
705 
706  if( !item )
707  return;
708 
709  switch( item->Type() )
710  {
711  case PCB_LINE_T:
712  case PCB_MODULE_EDGE_T:
713  {
714  const DRAWSEGMENT* segment = static_cast<const DRAWSEGMENT*>( item );
715 
716  switch( segment->GetShape() )
717  {
718  case S_SEGMENT:
719  m_editPoints->Point( SEG_START ).SetPosition( segment->GetStart() );
720  m_editPoints->Point( SEG_END ).SetPosition( segment->GetEnd() );
721  break;
722 
723  case S_ARC:
724  m_editPoints->Point( ARC_CENTER ).SetPosition( segment->GetCenter() );
725  m_editPoints->Point( ARC_START ).SetPosition( segment->GetArcStart() );
726  m_editPoints->Point( ARC_MID ).SetPosition( segment->GetArcMid() );
727  m_editPoints->Point( ARC_END ).SetPosition( segment->GetArcEnd() );
728  break;
729 
730  case S_CIRCLE:
731  m_editPoints->Point( CIRC_CENTER ).SetPosition( segment->GetCenter() );
732  m_editPoints->Point( CIRC_END ).SetPosition( segment->GetEnd() );
733  break;
734 
735  case S_POLYGON:
736  {
737  const auto& points = segment->BuildPolyPointsList();
738 
739  if( m_editPoints->PointsSize() != (unsigned) points.size() )
740  {
741  getView()->Remove( m_editPoints.get() );
742  m_editedPoint = nullptr;
743  m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() );
744  getView()->Add( m_editPoints.get() );
745  }
746  else
747  {
748  for( unsigned i = 0; i < points.size(); i++ )
749  m_editPoints->Point( i ).SetPosition( points[i] );
750  }
751  break;
752  }
753 
754  case S_CURVE:
755  m_editPoints->Point( BEZIER_CURVE_START ).SetPosition( segment->GetStart() );
756  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ).SetPosition( segment->GetBezControl1() );
757  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ).SetPosition( segment->GetBezControl2() );
758  m_editPoints->Point( BEZIER_CURVE_END ).SetPosition( segment->GetEnd() );
759  break;
760 
761  default: // suppress warnings
762  break;
763  }
764 
765  break;
766  }
767 
768  case PCB_ZONE_AREA_T:
769  {
770  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
771  const SHAPE_POLY_SET* outline = zone->Outline();
772 
773  if( m_editPoints->PointsSize() != (unsigned) outline->TotalVertices() )
774  {
775  getView()->Remove( m_editPoints.get() );
776  m_editedPoint = nullptr;
777  m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() );
778  getView()->Add( m_editPoints.get() );
779  }
780  else
781  {
782  for( int i = 0; i < outline->TotalVertices(); ++i )
783  m_editPoints->Point( i ).SetPosition( outline->CVertex( i ) );
784  }
785 
786  break;
787  }
788 
789  case PCB_DIMENSION_T:
790  {
791  const DIMENSION* dimension = static_cast<const DIMENSION*>( item );
792 
793  m_editPoints->Point( DIM_CROSSBARO ).SetPosition( dimension->m_crossBarO );
794  m_editPoints->Point( DIM_CROSSBARF ).SetPosition( dimension->m_crossBarF );
795  m_editPoints->Point( DIM_FEATUREGO ).SetPosition( dimension->m_featureLineGO );
796  m_editPoints->Point( DIM_FEATUREDO ).SetPosition( dimension->m_featureLineDO );
797  break;
798  }
799 
800  default:
801  break;
802  }
803 
804  getView()->Update( m_editPoints.get() );
805 }
806 
807 
809 {
811 
812  if( aPoint )
813  {
814  controls->ForceCursorPosition( true, aPoint->GetPosition() );
815  controls->ShowCursor( true );
816  }
817  else
818  {
819  controls->ShowCursor( false );
820  controls->ForceCursorPosition( false );
821  }
822 
823  m_editedPoint = aPoint;
824 }
825 
826 
827 void POINT_EDITOR::setAltConstraint( bool aEnabled )
828 {
829  if( aEnabled )
830  {
831  EDIT_LINE* line = dynamic_cast<EDIT_LINE*>( m_editedPoint );
832 
833  if( line && m_editPoints->GetParent()->Type() == PCB_ZONE_AREA_T )
834  {
836  }
837  else
838  {
839  // Find a proper constraining point for 45 degrees mode
842  }
843  }
844  else
845  {
846  m_altConstraint.reset();
847  }
848 }
849 
850 
852 {
853  EDA_ITEM* item = m_editPoints->GetParent();
854 
855  switch( item->Type() )
856  {
857  case PCB_LINE_T:
858  case PCB_MODULE_EDGE_T:
859  {
860  const DRAWSEGMENT* segment = static_cast<const DRAWSEGMENT*>( item );
861  {
862  switch( segment->GetShape() )
863  {
864  case S_SEGMENT:
865  return *( m_editPoints->Next( *m_editedPoint ) ); // select the other end of line
866 
867  case S_ARC:
868  case S_CIRCLE:
869  return m_editPoints->Point( CIRC_CENTER );
870 
871  default: // suppress warnings
872  break;
873  }
874  }
875 
876  break;
877  }
878 
879  case PCB_DIMENSION_T:
880  {
881  // Constraint for crossbar
882  if( isModified( m_editPoints->Point( DIM_FEATUREGO ) ) )
883  return m_editPoints->Point( DIM_FEATUREDO );
884 
885  else if( isModified( m_editPoints->Point( DIM_FEATUREDO ) ) )
886  return m_editPoints->Point( DIM_FEATUREGO );
887 
888  else
889  return EDIT_POINT( m_editedPoint->GetPosition() ); // no constraint
890 
891  break;
892  }
893 
894  default:
895  break;
896  }
897 
898  // In any other case we may align item to its original position
899  return m_original;
900 }
901 
902 
904 {
910 }
911 
912 
914 {
915  const auto type = aItem.Type();
916 
917  // Works only for zones and line segments
918  return type == PCB_ZONE_AREA_T ||
919  ( ( type == PCB_LINE_T || type == PCB_MODULE_EDGE_T ) &&
920  ( static_cast<const DRAWSEGMENT&>( aItem ).GetShape() == S_SEGMENT ||
921  static_cast<const DRAWSEGMENT&>( aItem ).GetShape() == S_POLYGON ) );
922 }
923 
924 
926 {
927  if( aSelection.Size() != 1 )
928  return false;
929 
930  const EDA_ITEM* item = aSelection.Front();
931 
932  return ( item != nullptr ) && canAddCorner( *item );
933 }
934 
935 
936 // Finds a corresponding vertex in a polygon set
937 static std::pair<bool, SHAPE_POLY_SET::VERTEX_INDEX>
938 findVertex( SHAPE_POLY_SET& aPolySet, const EDIT_POINT& aPoint )
939 {
940  for( auto it = aPolySet.IterateWithHoles(); it; ++it )
941  {
942  auto vertexIdx = it.GetIndex();
943 
944  if( aPolySet.Vertex( vertexIdx ) == aPoint.GetPosition() )
945  return std::make_pair( true, vertexIdx );
946  }
947 
948  return std::make_pair( false, SHAPE_POLY_SET::VERTEX_INDEX() );
949 }
950 
951 
953 {
954  if( !m_editPoints || !m_editedPoint )
955  return false;
956 
957  EDA_ITEM* item = m_editPoints->GetParent();
958 
959  if( !item || !( item->Type() == PCB_ZONE_AREA_T ||
960  ( ( item->Type() == PCB_MODULE_EDGE_T || item->Type() == PCB_LINE_T ) &&
961  static_cast<DRAWSEGMENT*>( item )->GetShape() == S_POLYGON ) ) )
962  return false;
963 
964  SHAPE_POLY_SET *polyset;
965 
966  if( item->Type() == PCB_ZONE_AREA_T )
967  polyset = static_cast<ZONE_CONTAINER*>( item )->Outline();
968  else
969  polyset = &static_cast<DRAWSEGMENT*>( item )->GetPolyShape();
970 
971  auto vertex = findVertex( *polyset, *m_editedPoint );
972 
973  if( !vertex.first )
974  return false;
975 
976  const auto& vertexIdx = vertex.second;
977 
978  // Check if there are enough vertices so one can be removed without
979  // degenerating the polygon.
980  // The first condition allows one to remove all corners from holes (when
981  // there are only 2 vertices left, a hole is removed).
982  if( vertexIdx.m_contour == 0 && polyset->Polygon( vertexIdx.m_polygon )[vertexIdx.m_contour].PointCount() <= 3 )
983  return false;
984 
985  // Remove corner does not work with lines
986  if( dynamic_cast<EDIT_LINE*>( m_editedPoint ) )
987  return false;
988 
989  return m_editedPoint != NULL;
990 }
991 
992 
994 {
995  if( !m_editPoints )
996  return 0;
997 
998  EDA_ITEM* item = m_editPoints->GetParent();
999  PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
1000  const VECTOR2I& cursorPos = getViewControls()->GetCursorPosition();
1001 
1002  // called without an active edited polygon
1003  if( !item || !canAddCorner( *item ) )
1004  return 0;
1005 
1006  DRAWSEGMENT* graphicItem = dynamic_cast<DRAWSEGMENT*>( item );
1007  BOARD_COMMIT commit( frame );
1008 
1009  if( item->Type() == PCB_ZONE_AREA_T ||
1010  ( graphicItem && graphicItem->GetShape() == S_POLYGON ) )
1011  {
1012  unsigned int nearestIdx = 0;
1013  unsigned int nextNearestIdx = 0;
1014  unsigned int nearestDist = INT_MAX;
1015  unsigned int firstPointInContour = 0;
1016  SHAPE_POLY_SET* zoneOutline;
1017 
1018  if( item->Type() == PCB_ZONE_AREA_T )
1019  {
1020  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
1021  zoneOutline = zone->Outline();
1022  zone->SetNeedRefill( true );
1023  }
1024  else
1025  zoneOutline = &( graphicItem->GetPolyShape() );
1026 
1027  commit.Modify( item );
1028 
1029  // Search the best outline segment to add a new corner
1030  // and therefore break this segment into two segments
1031 
1032  // Object to iterate through the corners of the outlines (main contour and its holes)
1033  SHAPE_POLY_SET::ITERATOR iterator = zoneOutline->Iterate( 0,
1034  zoneOutline->OutlineCount()-1, /* IterateHoles */ true );
1035  int curr_idx = 0;
1036 
1037  // Iterate through all the corners of the outlines and search the best segment
1038  for( ; iterator; iterator++, curr_idx++ )
1039  {
1040  int jj = curr_idx+1;
1041 
1042  if( iterator.IsEndContour() )
1043  { // We reach the last point of the current contour (main or hole)
1044  jj = firstPointInContour;
1045  firstPointInContour = curr_idx+1; // Prepare next contour analysis
1046  }
1047 
1048  SEG curr_segment( zoneOutline->Vertex( curr_idx ), zoneOutline->Vertex( jj ) );
1049 
1050  unsigned int distance = curr_segment.Distance( cursorPos );
1051 
1052  if( distance < nearestDist )
1053  {
1054  nearestDist = distance;
1055  nearestIdx = curr_idx;
1056  nextNearestIdx = jj;
1057  }
1058  }
1059 
1060  // Find the point on the closest segment
1061  VECTOR2I sideOrigin = zoneOutline->Vertex( nearestIdx );
1062  VECTOR2I sideEnd = zoneOutline->Vertex( nextNearestIdx );
1063  SEG nearestSide( sideOrigin, sideEnd );
1064  VECTOR2I nearestPoint = nearestSide.NearestPoint( cursorPos );
1065 
1066  // Do not add points that have the same coordinates as ones that already belong to polygon
1067  // instead, add a point in the middle of the side
1068  if( nearestPoint == sideOrigin || nearestPoint == sideEnd )
1069  nearestPoint = ( sideOrigin + sideEnd ) / 2;
1070 
1071  zoneOutline->InsertVertex( nextNearestIdx, nearestPoint );
1072 
1073  // We re-hatch the filled zones but not polygons
1074  if( item->Type() == PCB_ZONE_AREA_T )
1075  static_cast<ZONE_CONTAINER*>( item )->Hatch();
1076 
1077 
1078  commit.Push( _( "Add a zone corner" ) );
1079  }
1080 
1081  else if( graphicItem && graphicItem->GetShape() == S_SEGMENT )
1082  {
1083  commit.Modify( graphicItem );
1084 
1085  SEG seg( graphicItem->GetStart(), graphicItem->GetEnd() );
1086  VECTOR2I nearestPoint = seg.NearestPoint( cursorPos );
1087 
1088  // Move the end of the line to the break point..
1089  graphicItem->SetEnd( wxPoint( nearestPoint.x, nearestPoint.y ) );
1090 
1091  // and add another one starting from the break point
1092  DRAWSEGMENT* newSegment;
1093 
1094  if( item->Type() == PCB_MODULE_EDGE_T )
1095  {
1096  EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( graphicItem );
1097  assert( edge->GetParent()->Type() == PCB_MODULE_T );
1098  newSegment = new EDGE_MODULE( *edge );
1099  }
1100  else
1101  {
1102  newSegment = new DRAWSEGMENT( *graphicItem );
1103  }
1104 
1105  newSegment->ClearSelected();
1106  newSegment->SetStart( wxPoint( nearestPoint.x, nearestPoint.y ) );
1107  newSegment->SetEnd( wxPoint( seg.B.x, seg.B.y ) );
1108 
1109  commit.Add( newSegment );
1110  commit.Push( _( "Split segment" ) );
1111  }
1112 
1113  updatePoints();
1114  return 0;
1115 }
1116 
1117 
1119 {
1120  if( !m_editPoints || !m_editedPoint )
1121  return 0;
1122 
1123  EDA_ITEM* item = m_editPoints->GetParent();
1124 
1125  if( !item )
1126  return 0;
1127 
1128  SHAPE_POLY_SET* polygon = nullptr;
1129 
1130  if( item->Type() == PCB_ZONE_AREA_T)
1131  {
1132  auto zone = static_cast<ZONE_CONTAINER*>( item );
1133  polygon = zone->Outline();
1134  zone->SetNeedRefill( true );
1135  }
1136  else if( (item->Type() == PCB_MODULE_EDGE_T ) || ( item->Type() == PCB_LINE_T ) )
1137  {
1138  auto ds = static_cast<DRAWSEGMENT*>( item );
1139 
1140  if( ds->GetShape() == S_POLYGON )
1141  polygon = &ds->GetPolyShape();
1142  }
1143 
1144  if( !polygon )
1145  return 0;
1146 
1147  PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
1148  BOARD_COMMIT commit( frame );
1149  auto vertex = findVertex( *polygon, *m_editedPoint );
1150 
1151  if( vertex.first )
1152  {
1153  const auto& vertexIdx = vertex.second;
1154  auto& outline = polygon->Polygon( vertexIdx.m_polygon )[vertexIdx.m_contour];
1155  bool valid = true;
1156 
1157  if( outline.PointCount() > 3 )
1158  {
1159  // the usual case: remove just the corner when there are >3 vertices
1160  commit.Modify( item );
1161  polygon->RemoveVertex( vertexIdx );
1162  valid = validatePolygon( *polygon );
1163  }
1164  else
1165  {
1166  // either remove a hole or the polygon when there are <= 3 corners
1167  if( vertexIdx.m_contour > 0 )
1168  {
1169  // remove hole
1170  commit.Modify( item );
1171  polygon->RemoveContour( vertexIdx.m_contour );
1172  }
1173  else
1174  {
1176  commit.Remove( item );
1177  }
1178  }
1179 
1180  setEditedPoint( nullptr );
1181 
1182  if( valid )
1183  {
1184  commit.Push( _( "Remove a zone/polygon corner" ) );
1185 
1186  // Refresh zone hatching
1187  if( item->Type() == PCB_ZONE_AREA_T)
1188  static_cast<ZONE_CONTAINER*>( item )->Hatch();
1189 
1190  updatePoints();
1191  }
1192  else
1193  {
1195  getView()->Remove( m_editPoints.get() );
1196  commit.Revert();
1197  m_editPoints.reset();
1198  }
1199  }
1200 
1201  return 0;
1202 }
1203 
1204 
1206 {
1207  m_refill = true; // zone has been modified outside the point editor tool
1208  updatePoints();
1209  return 0;
1210 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
const wxPoint GetArcMid() const
int TotalVertices() const
Returns total number of vertices stored in the set.
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
Class EC_CONVERGING.
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
int OnSelectionChange(const TOOL_EVENT &aEvent)
Function OnSelected()
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
static const TOOL_EVENT SelectedEvent
Event sent after an item is selected.
Definition: actions.h:132
void setTransitions() override
Sets up handlers for various events.
int OutlineCount() const
Returns the number of outlines in the set
bool IsEndContour() const
Function IsEndContour.
virtual void Move(const wxPoint &aMoveVector) override
Function Move move this object.
BOARD * board() const
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
static const TOOL_EVENT UnselectedEvent
Event sent after an item is unselected.
Definition: actions.h:133
This file is part of the common library.
wxPoint m_crossBarF
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
const wxPoint GetCenter() const override
Function GetCenter()
void ClearSelected()
Definition: base_struct.h:237
COMMIT & Add(EDA_ITEM *aItem)
Adds a new item to the model
Definition: commit.h:78
VIEW_CONTROLS class definition.
STROKE_T GetShape() const
const wxPoint GetArcEnd() const
void updateEditedPoint(const TOOL_EVENT &aEvent)
Updates which point is being edited.
Class SELECTION_TOOL.
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Returns the index-th vertex in a given hole outline within a given outline
Class BOARD to handle a board.
Class STATUS_TEXT_POPUP.
Definition: status_popup.h:79
virtual void Revert() override
Revertes the commit by restoring the modifed items state.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
TOOL_MENU & GetToolMenu()
polygon (not yet used for tracks, but could be in microwave apps)
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:216
Class EDIT_LINE.
Definition: edit_points.h:207
int removeCorner(const TOOL_EVENT &aEvent)
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_BezierPoints vertex list that approximate the Bezier curve by a list of segments Has me...
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:100
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:376
OPT_TOOL_EVENT Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:260
CONST_ITERATOR CIterateWithHoles(int aOutline) const
bool IsMotion() const
Definition: tool_event.h:290
virtual void SetSnapping(bool aEnabled)
Function SetSnapping() Enables/disables snapping cursor to grid.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
double RAD2DECIDEG(double rad)
Definition: trigo.h:213
Struct VERTEX_INDEX.
Classes to handle copper zones.
void setAltConstraint(bool aEnabled)
Sets up an alternative constraint (typically enabled upon a modifier key being pressed).
usual segment : line with rounded ends
VECTOR2I BestSnapAnchor(const VECTOR2I &aOrigin, BOARD_ITEM *aDraggedItem)
bool isModified(const EDIT_POINT &aPoint) const
Returns true if aPoint is the currently modified point.
Definition: point_editor.h:112
std::unique_ptr< STATUS_TEXT_POPUP > m_statusPopup
Definition: point_editor.h:86
ITERATOR Iterate(int aFirst, int aLast, bool aIterateHoles=false)
Function Iterate returns an object to iterate through the points of the polygons between aFirst and a...
CIRCLE_POINTS
const std::vector< wxPoint > BuildPolyPointsList() const
Build and return the list of corners in a std::vector<wxPoint> It must be used only to convert the SH...
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
void SetCenter(const wxPoint &aCenterPoint)
For arcs and circles:
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
void SetBezControl2(const wxPoint &aPoint)
Class EC_LINE.
virtual void Remove(VIEW_ITEM *aItem) override
Function Remove() Removes a VIEW_ITEM from the view.
Definition: pcb_view.cpp:74
Class EC_45DEGREE.
void updateItem() const
Updates item's points with edit points.
static const TOOL_EVENT SelectedItemsModified
Definition: actions.h:136
bool removeCornerCondition(const SELECTION &aSelection)
Condition to display "Remove corner" context menu entry.
Class EC_CIRCLE.
VECTOR2I & Vertex(int aIndex, int aOutline, int aHole)
Returns the index-th vertex in a given hole outline within a given outline
wxPoint m_featureLineGO
VECTOR2D GetGridPoint(const VECTOR2D &aPoint) const
Function GetGridPoint() For a given point it returns the nearest point belonging to the grid in world...
void PassEvent()
Allows a tool to pass the already handled event to the next tool on the stack.
Definition: tool_manager.h:356
DIMENSION class definition.
std::shared_ptr< EDIT_POINTS > m_editPoints
Currently available edit points.
Definition: point_editor.h:75
void finishItem()
Applies the last changes to the edited item.
class MODULE, a footprint
Definition: typeinfo.h:89
void SetProgressReporter(WX_PROGRESS_REPORTER *aReporter)
Definition: zone_filler.cpp:97
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:280
void SetOrigin(const wxPoint &aOrigin)
Function SetOrigin Sets a new origin of the crossbar line.
Class LSET is a set of PCB_LAYER_IDs.
virtual VECTOR2I GetPosition() const
Function GetPosition()
Definition: edit_points.h:68
const wxPoint & GetEnd()
Function GetEnd.
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
ITERATOR IterateWithHoles(int aOutline)
Function IterateWithHoles.
Class SHAPE_POLY_SET.
SEG_POINTS
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
static TOOL_ACTION pointEditorAddCorner
Break outline (insert additional points to an edge)
Definition: pcb_actions.h:189
static TOOL_ACTION pointEditorRemoveCorner
Removes a corner.
Definition: pcb_actions.h:192
void SetEnd(const wxPoint &aEnd)
Function SetEnd Sets a new end of the crossbar line.
Arcs (with rounded ends)
Class TOOL_EVENT.
Definition: tool_event.h:167
std::shared_ptr< EDIT_CONSTRAINT< EDIT_POINT > > m_altConstraint
Definition: point_editor.h:78
COMMIT & StageItems(const Range &aRange, CHANGE_TYPE aChangeType)
Definition: commit.h:116
bool validatePolygon(SHAPE_POLY_SET &aModified, const SHAPE_POLY_SET *aOriginal=nullptr) const
Validates a polygon and restores it to its original version if available.
KIGFX::PCB_VIEW * view() const
DIMENSION_POINTS
SELECTION & GetSelection()
Function GetSelection()
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Function NearestPoint()
Definition: seg.h:374
Class VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (...
const VECTOR2D DragOrigin() const
Returns the point where dragging has started.
Definition: tool_event.h:264
static const TOOL_EVENT ClearedEvent
Event sent after selection is cleared.
Definition: actions.h:134
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
static LSET AllLayersMask()
Definition: lset.cpp:713
const wxPoint & GetArcStart() const
COMMIT & Remove(EDA_ITEM *aItem)
Removes a new item from the model
Definition: commit.h:90
SHAPE_POLY_SET & GetPolyShape()
bool Fill(const std::vector< ZONE_CONTAINER * > &aZones, bool aCheck=false)
SELECTION_TOOL * m_selectionTool
Selection tool used for obtaining selected items
Definition: point_editor.h:66
Bezier Curve.
const wxPoint & GetOrigin() const
Function GetOrigin.
All active tools
Definition: tool_event.h:143
double Angle() const
Function Angle computes the angle of the vector.
Definition: vector2d.h:306
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1539
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:98
PCB_EDIT_FRAME * frame() const
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:35
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
int GetWidth() const
void SetStart(const wxPoint &aStart)
void SetSnap(bool aSnap)
Definition: grid_helper.h:72
Definition: seg.h:36
EDIT_POINT get45DegConstrainer() const
Returns a point that should be used as a constrainer for 45 degrees mode.
double GetAngle() const
KIGFX::VIEW_CONTROLS * controls() const
Common, abstract interface for edit frames.
void SetHeight(int aHeight)
Function SetHeight Sets the length of feature lines.
void RemoveVertex(int aGlobalIndex)
Function RemoveVertex deletes the aGlobalIndex-th vertex.
Class ITERATOR_TEMPLATE.
Class TOOL_ACTION.
Definition: tool_action.h:46
size_t i
Definition: json11.cpp:597
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
static bool canAddCorner(const EDA_ITEM &aItem)
Determine if the tool can currently add a corner to the given item
int Size() const
Returns the number of selected parts.
Definition: selection.h:125
void Hatch()
Function Hatch computes the hatch lines depending on the hatch parameters and stores it in the zone's...
const wxPoint & GetBezControl2() const
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:157
void SetAuxAxes(bool aEnable, const VECTOR2I &aOrigin=VECTOR2I(0, 0), bool aEnableDiagonal=false)
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:80
void updatePoints()
Updates edit points with item's points.
void SetEnd(const wxPoint &aEnd)
static std::pair< bool, SHAPE_POLY_SET::VERTEX_INDEX > findVertex(SHAPE_POLY_SET &aPolySet, const EDIT_POINT &aPoint)
void SetAngle(double aAngle)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
EDIT_POINT m_original
Original position for the current drag point.
Definition: point_editor.h:72
void Activate()
Function Activate() Runs the tool.
void InsertVertex(int aGlobalIndex, VECTOR2I aNewVertex)
Function InsertVertex Adds a vertex in the globally indexed position aGlobalIndex.
wxPoint m_crossBarO
BEZIER_CURVE_POINTS
const wxPoint & GetBezControl1() const
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Function Add() Adds a VIEW_ITEM to the view.
Definition: pcb_view.cpp:58
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:346
void SetUseGrid(bool aGrid=true)
Definition: grid_helper.h:77
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Class EDIT_POINT.
Definition: edit_points.h:46
Module description (excepted pads)
POLYGON & Polygon(int aIndex)
Returns the aIndex-th subpolygon in the set
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:41
Class VIEW.
Definition: view.h:61
EDIT_POINT m_altConstrainer
Definition: point_editor.h:81
void UpdateMsgPanel() override
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
EDIT_POINT * m_editedPoint
Currently edited point, NULL if there is none.
Definition: point_editor.h:69
bool IsSelfIntersecting()
Function IsSelfIntersecting Checks whether any of the polygons in the set is self intersecting.
BOARD_ITEM_CONTAINER * GetParent() const
const SELECTION & selection() const
wxPoint m_featureLineDO
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Function AddItem()
const VECTOR2I GetArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc/circle, given three points on its circumference.
Definition: trigo.cpp:349
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
Class EC_SNAPLINE.
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void setEditedPoint(EDIT_POINT *aPoint)
Sets the current point being edited. NULL means none.
static void buildForPolyOutline(std::shared_ptr< EDIT_POINTS > points, const SHAPE_POLY_SET *aOutline, KIGFX::GAL *aGal)
Class DIMENSION.
const VECTOR2D Position() const
Returns mouse cursor position in world coordinates.
Definition: tool_event.h:258
virtual void ApplyConstraint()
Function ApplyConstraint()
Definition: edit_points.h:173
int addCorner(const TOOL_EVENT &aEvent)
TOOL_ACTION handlers.
int modifiedSelection(const TOOL_EVENT &aEvent)
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
ARC_POINTS
EDA_ITEM * Front() const
Definition: selection.h:155
void ClearFilledPolysList()
Function ClearFilledPolysList clears the list of filled polygons.
Definition: class_zone.h:570
static bool addCornerCondition(const SELECTION &aSelection)
Condition to display "Create corner" context menu entry.
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:486
KICAD_T Type() const
Function Type()
Definition: base_struct.h:204
Class GAL is the abstract interface for drawing on a 2D-surface.
void SetBezControl1(const wxPoint &aPoint)
static std::shared_ptr< EDIT_POINTS > Make(EDA_ITEM *aItem, KIGFX::GAL *aGal)
void RemoveContour(int aContourIdx, int aPolygonIdx=-1)
Function RemoveContour deletes the aContourIdx-th contour of the aPolygonIdx-th polygon in the set.
virtual void SetPosition(const VECTOR2I &aPosition)
Function SetPosition()
Definition: edit_points.h:105
void SetNeedRefill(bool aNeedRefill)
Definition: class_zone.h:191