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-2018 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>
49 
50 #include "zone_filler.h"
51 
52 // Point editor
53 TOOL_ACTION PCB_ACTIONS::pointEditorAddCorner( "pcbnew.PointEditor.addCorner",
54  AS_GLOBAL, WXK_INSERT,
55  _( "Create Corner" ), _( "Create a corner" ), add_corner_xpm );
56 
57 TOOL_ACTION PCB_ACTIONS::pointEditorRemoveCorner( "pcbnew.PointEditor.removeCorner",
58  AS_GLOBAL, 0,
59  _( "Remove Corner" ), _( "Remove corner" ), delete_xpm );
60 
61 
62 // Few constants to avoid using bare numbers for point indices
64 {
66 };
67 
69 {
71 };
72 
74 {
76 };
77 
79 {
84 };
85 
87 {
92 };
93 
95 {
96 private:
97 
98  static void buildForPolyOutline( std::shared_ptr<EDIT_POINTS> points,
99  const SHAPE_POLY_SET* aOutline, KIGFX::GAL* aGal )
100  {
101 
102  int cornersCount = aOutline->TotalVertices();
103 
104  for( auto iterator = aOutline->CIterateWithHoles(); iterator; iterator++ )
105  {
106  points->AddPoint( *iterator );
107 
108  if( iterator.IsEndContour() )
109  points->AddBreak();
110  }
111 
112  // Lines have to be added after creating edit points,
113  // as they use EDIT_POINT references
114  for( int i = 0; i < cornersCount - 1; ++i )
115  {
116  if( points->IsContourEnd( i ) )
117  {
118  points->AddLine( points->Point( i ),
119  points->Point( points->GetContourStartIdx( i ) ) );
120  }
121  else
122  {
123  points->AddLine( points->Point( i ), points->Point( i + 1 ) );
124  }
125 
126  points->Line( i ).SetConstraint( new EC_SNAPLINE( points->Line( i ),
127  std::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) );
128  }
129 
130  // The last missing line, connecting the last and the first polygon point
131  points->AddLine( points->Point( cornersCount - 1 ),
132  points->Point( points->GetContourStartIdx( cornersCount - 1 ) ) );
133 
134  points->Line( points->LinesSize() - 1 ).SetConstraint(
135  new EC_SNAPLINE( points->Line( points->LinesSize() - 1 ),
136  std::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) );
137  }
138 
139 public:
140  static std::shared_ptr<EDIT_POINTS> Make( EDA_ITEM* aItem, KIGFX::GAL* aGal )
141  {
142  std::shared_ptr<EDIT_POINTS> points = std::make_shared<EDIT_POINTS>( aItem );
143 
144  if( !aItem )
145  return points;
146 
147  // Generate list of edit points basing on the item type
148  switch( aItem->Type() )
149  {
150  case PCB_LINE_T:
151  case PCB_MODULE_EDGE_T:
152  {
153  const DRAWSEGMENT* segment = static_cast<const DRAWSEGMENT*>( aItem );
154 
155  switch( segment->GetShape() )
156  {
157  case S_SEGMENT:
158  points->AddPoint( segment->GetStart() );
159  points->AddPoint( segment->GetEnd() );
160  break;
161 
162  case S_ARC:
163  points->AddPoint( segment->GetCenter() );
164  points->AddPoint( segment->GetArcStart() );
165  points->AddPoint( segment->GetArcEnd() );
166 
167  // Set constraints
168  // Arc end has to stay at the same radius as the start
169  points->Point( ARC_END ).SetConstraint( new EC_CIRCLE( points->Point( ARC_END ),
170  points->Point( ARC_CENTER ),
171  points->Point( ARC_START ) ) );
172  break;
173 
174  case S_CIRCLE:
175  points->AddPoint( segment->GetCenter() );
176  points->AddPoint( segment->GetEnd() );
177 
178  break;
179 
180  case S_POLYGON:
181  buildForPolyOutline( points, &segment->GetPolyShape(), aGal );
182  break;
183 
184  case S_CURVE:
185  points->AddPoint( segment->GetStart() );
186  points->AddPoint( segment->GetBezControl1() );
187  points->AddPoint( segment->GetBezControl2() );
188  points->AddPoint( segment->GetEnd() );
189  break;
190 
191  default: // suppress warnings
192  break;
193  }
194 
195  break;
196  }
197 
198  case PCB_ZONE_AREA_T:
199  {
200  auto zone = static_cast<const ZONE_CONTAINER*>( aItem );
201  buildForPolyOutline( points, zone->Outline(), aGal );
202  break;
203  }
204 
205  case PCB_DIMENSION_T:
206  {
207  const DIMENSION* dimension = static_cast<const DIMENSION*>( aItem );
208 
209  points->AddPoint( dimension->m_crossBarO );
210  points->AddPoint( dimension->m_crossBarF );
211  points->AddPoint( dimension->m_featureLineGO );
212  points->AddPoint( dimension->m_featureLineDO );
213 
214  // Dimension height setting - edit points should move only along the feature lines
215  points->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARO ),
216  points->Point( DIM_FEATUREGO ) ) );
217  points->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARF ),
218  points->Point( DIM_FEATUREDO ) ) );
219 
220  break;
221  }
222 
223  default:
224  points.reset();
225  break;
226  }
227 
228  return points;
229  }
230 
231 private:
233 };
234 
235 
237  PCB_TOOL( "pcbnew.PointEditor" ), m_selectionTool( NULL ), m_editedPoint( NULL ),
238  m_original( VECTOR2I( 0, 0 ) ), m_altConstrainer( VECTOR2I( 0, 0 ) ), m_refill( false )
239 {
240 }
241 
242 
244 {
245  m_refill = false;
246  m_editPoints.reset();
247  m_altConstraint.reset();
248  getViewControls()->SetAutoPan( false );
249 
250  m_statusPopup.reset( new STATUS_TEXT_POPUP( getEditFrame<PCB_BASE_EDIT_FRAME>() ) );
251  m_statusPopup->SetTextColor( wxColour( 255, 0, 0 ) );
252  m_statusPopup->SetText( _( "Self-intersecting polygons are not allowed" ) );
253 }
254 
255 
257 {
258  // Find the selection tool, so they can cooperate
259  m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ) );
260 
261  if( !m_selectionTool )
262  {
263  DisplayError( NULL, _( "pcbnew.InteractiveSelection tool is not available" ) );
264  return false;
265  }
266 
267  auto& menu = m_selectionTool->GetToolMenu().GetMenu();
270  std::bind( &POINT_EDITOR::removeCornerCondition, this, _1 ) );
271 
272  return true;
273 }
274 
275 
277 {
278  EDIT_POINT* point = m_editedPoint;
279 
280  if( aEvent.IsMotion() )
281  {
282  point = m_editPoints->FindPoint( aEvent.Position(), getView() );
283  }
284  else if( aEvent.IsDrag( BUT_LEFT ) )
285  {
286  point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
287  }
288 
289  if( m_editedPoint != point )
290  setEditedPoint( point );
291 }
292 
293 
295 {
296  if( !m_selectionTool )
297  return 0;
298 
300 
301  if( selection.Size() != 1 )
302  return 0;
303 
304  Activate();
305 
307  KIGFX::VIEW* view = getView();
308  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
309 
310  controls->ShowCursor( true );
311 
312  GRID_HELPER grid( editFrame );
313  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
314 
315  m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() );
316 
317  if( !m_editPoints )
318  return 0;
319 
320  view->Add( m_editPoints.get() );
321  setEditedPoint( nullptr );
322  m_refill = false;
323  bool modified = false;
324  bool revert = false;
325 
326  BOARD_COMMIT commit( editFrame );
327  LSET snapLayers = item->GetLayerSet();
328 
329  if( item->Type() == PCB_DIMENSION_T )
330  snapLayers = LSET::AllLayersMask();
331 
332  // Main loop: keep receiving events
333  while( OPT_TOOL_EVENT evt = Wait() )
334  {
335  if( revert )
336  break;
337 
338  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
339  grid.SetUseGrid( !evt->Modifier( MD_ALT ) );
340  controls->SetSnapping( !evt->Modifier( MD_ALT ) );
341 
342  if( !m_editPoints ||
343  evt->Matches( m_selectionTool->ClearedEvent ) ||
344  evt->Matches( m_selectionTool->UnselectedEvent ) ||
345  evt->Matches( m_selectionTool->SelectedEvent ) )
346  {
347  break;
348  }
349 
350  if ( !modified )
351  updateEditedPoint( *evt );
352 
353  if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
354  {
355  if( !modified )
356  {
357  commit.StageItems( selection, CHT_MODIFY );
358 
359  controls->ForceCursorPosition( false );
360  m_original = *m_editedPoint; // Save the original position
361  controls->SetAutoPan( true );
362  modified = true;
363  grid.SetAuxAxes( true, m_original.GetPosition(), true );
364  }
365 
366  //TODO: unify the constraints to solve simultaneously instead of sequentially
367  m_editedPoint->SetPosition( grid.BestSnapAnchor( evt->Position(),
368  snapLayers, { item } ) );
369  bool enableAltConstraint = !!evt->Modifier( MD_CTRL );
370 
371  if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint
372  setAltConstraint( enableAltConstraint );
373 
374  if( m_altConstraint )
375  m_altConstraint->Apply();
376  else
378 
380  snapLayers, { item } ) );
381 
382  updateItem();
383  updatePoints();
384  }
385 
386  else if( evt->IsMouseUp( BUT_LEFT ) )
387  {
388  controls->SetAutoPan( false );
389  setAltConstraint( false );
390 
391  if( modified )
392  {
393  commit.Push( _( "Drag a corner" ) );
394  modified = false;
395  m_refill = true;
396  }
397 
398  m_toolMgr->PassEvent();
399  }
400 
401  else if( evt->IsCancel() )
402  {
403  if( modified ) // Restore the last change
404  revert = true;
405 
406  // Let the selection tool receive the event too
407  m_toolMgr->PassEvent();
408 
409  // Do not exit right now, let the selection clear the selection
410  //break;
411  }
412 
413  else
414  {
415  m_toolMgr->PassEvent();
416  }
417  }
418 
419  if( m_editPoints )
420  {
421  view->Remove( m_editPoints.get() );
422 
423  if( modified && revert )
424  commit.Revert();
425 
426  finishItem();
427  m_editPoints.reset();
428  }
429 
430  frame()->UpdateMsgPanel();
431 
432  return 0;
433 }
434 
435 
437 {
438  EDA_ITEM* item = m_editPoints->GetParent();
439 
440  if( !item )
441  return;
442 
443  switch( item->Type() )
444  {
445  case PCB_LINE_T:
446  case PCB_MODULE_EDGE_T:
447  {
448  DRAWSEGMENT* segment = static_cast<DRAWSEGMENT*>( item );
449  switch( segment->GetShape() )
450  {
451  case S_SEGMENT:
452  if( isModified( m_editPoints->Point( SEG_START ) ) )
453  segment->SetStart( wxPoint( m_editPoints->Point( SEG_START ).GetPosition().x,
454  m_editPoints->Point( SEG_START ).GetPosition().y ) );
455 
456  else if( isModified( m_editPoints->Point( SEG_END ) ) )
457  segment->SetEnd( wxPoint( m_editPoints->Point( SEG_END ).GetPosition().x,
458  m_editPoints->Point( SEG_END ).GetPosition().y ) );
459 
460  break;
461 
462  case S_ARC:
463  {
464  const VECTOR2I& center = m_editPoints->Point( ARC_CENTER ).GetPosition();
465  const VECTOR2I& start = m_editPoints->Point( ARC_START ).GetPosition();
466  const VECTOR2I& end = m_editPoints->Point( ARC_END ).GetPosition();
467 
468  if( center != segment->GetCenter() )
469  {
470  wxPoint moveVector = wxPoint( center.x, center.y ) - segment->GetCenter();
471  segment->Move( moveVector );
472 
473  m_editPoints->Point( ARC_START ).SetPosition( segment->GetArcStart() );
474  m_editPoints->Point( ARC_END ).SetPosition( segment->GetArcEnd() );
475  }
476 
477  else
478  {
479  segment->SetArcStart( wxPoint( start.x, start.y ) );
480 
481  VECTOR2D startLine = start - center;
482  VECTOR2I endLine = end - center;
483  double newAngle = RAD2DECIDEG( endLine.Angle() - startLine.Angle() );
484 
485  // Adjust the new angle to (counter)clockwise setting
486  bool clockwise = ( segment->GetAngle() > 0 );
487 
488  if( clockwise && newAngle < 0.0 )
489  newAngle += 3600.0;
490  else if( !clockwise && newAngle > 0.0 )
491  newAngle -= 3600.0;
492 
493  segment->SetAngle( newAngle );
494  }
495 
496  break;
497  }
498 
499  case S_CIRCLE:
500  {
501  const VECTOR2I& center = m_editPoints->Point( CIRC_CENTER ).GetPosition();
502  const VECTOR2I& end = m_editPoints->Point( CIRC_END ).GetPosition();
503 
504  if( isModified( m_editPoints->Point( CIRC_CENTER ) ) )
505  {
506  wxPoint moveVector = wxPoint( center.x, center.y ) - segment->GetCenter();
507  segment->Move( moveVector );
508  }
509  else
510  {
511  segment->SetEnd( wxPoint( end.x, end.y ) );
512  }
513 
514  break;
515  }
516 
517  case S_POLYGON:
518  {
519  SHAPE_POLY_SET& outline = segment->GetPolyShape();
520 
521  for( int i = 0; i < outline.TotalVertices(); ++i )
522  outline.Vertex( i ) = m_editPoints->Point( i ).GetPosition();
523 
524  validatePolygon( outline );
525  break;
526  }
527 
528  case S_CURVE:
529  if( isModified( m_editPoints->Point( BEZIER_CURVE_START ) ) )
530  segment->SetStart( wxPoint( m_editPoints->Point( BEZIER_CURVE_START ).GetPosition().x,
531  m_editPoints->Point( BEZIER_CURVE_START ).GetPosition().y ) );
532  else if( isModified( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ) ) )
533  segment->SetBezControl1( wxPoint( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ).GetPosition().x,
534  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ).GetPosition().y ) );
535  else if( isModified( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ) ) )
536  segment->SetBezControl2( wxPoint( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ).GetPosition().x,
537  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ).GetPosition().y ) );
538  else if( isModified( m_editPoints->Point( BEZIER_CURVE_END ) ) )
539  segment->SetEnd( wxPoint( m_editPoints->Point( BEZIER_CURVE_END ).GetPosition().x,
540  m_editPoints->Point( BEZIER_CURVE_END ).GetPosition().y ) );
541 
542  segment->RebuildBezierToSegmentsPointsList( segment->GetWidth() );
543  break;
544 
545  default: // suppress warnings
546  break;
547  }
548 
549  // Update relative coordinates for module edges
550  if( EDGE_MODULE* edge = dyn_cast<EDGE_MODULE*>( item ) )
551  edge->SetLocalCoord();
552 
553  break;
554  }
555 
556  case PCB_ZONE_AREA_T:
557  {
558  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
559  zone->ClearFilledPolysList();
560  SHAPE_POLY_SET& outline = *zone->Outline();
561 
562  for( int i = 0; i < outline.TotalVertices(); ++i )
563  outline.Vertex( i ) = m_editPoints->Point( i ).GetPosition();
564 
565  validatePolygon( outline );
566  zone->Hatch();
567  break;
568  }
569 
570  case PCB_DIMENSION_T:
571  {
572  DIMENSION* dimension = static_cast<DIMENSION*>( item );
573 
574  // Check which point is currently modified and updated dimension's points respectively
575  if( isModified( m_editPoints->Point( DIM_CROSSBARO ) ) )
576  {
577  VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetOrigin() );
578  VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );
579 
580  if( featureLine.Cross( crossBar ) > 0 )
581  dimension->SetHeight( -featureLine.EuclideanNorm() );
582  else
583  dimension->SetHeight( featureLine.EuclideanNorm() );
584  }
585 
586  else if( isModified( m_editPoints->Point( DIM_CROSSBARF ) ) )
587  {
588  VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetEnd() );
589  VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );
590 
591  if( featureLine.Cross( crossBar ) > 0 )
592  dimension->SetHeight( -featureLine.EuclideanNorm() );
593  else
594  dimension->SetHeight( featureLine.EuclideanNorm() );
595  }
596 
597  else if( isModified( m_editPoints->Point( DIM_FEATUREGO ) ) )
598  {
599  dimension->SetOrigin( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ) );
600  m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
601  m_editPoints->Point( DIM_FEATUREGO ) ) );
602  m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
603  m_editPoints->Point( DIM_FEATUREDO ) ) );
604  }
605 
606  else if( isModified( m_editPoints->Point( DIM_FEATUREDO ) ) )
607  {
608  dimension->SetEnd( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ) );
609  m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
610  m_editPoints->Point( DIM_FEATUREGO ) ) );
611  m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
612  m_editPoints->Point( DIM_FEATUREDO ) ) );
613  }
614 
615  break;
616  }
617 
618  default:
619  break;
620  }
621 
622  if( frame() )
623  frame()->SetMsgPanel( item );
624 }
625 
626 
628 {
629  auto item = m_editPoints->GetParent();
630 
631  if( !item )
632  return;
633 
634  if( item->Type() == PCB_ZONE_AREA_T )
635  {
636  auto zone = static_cast<ZONE_CONTAINER*>( item );
637 
638  if( zone->IsFilled() && m_refill )
639  {
640  ZONE_FILLER filler( board() );
641  filler.Fill( { zone } );
642  }
643  }
644 }
645 
646 
647 bool POINT_EDITOR::validatePolygon( SHAPE_POLY_SET& aModified, const SHAPE_POLY_SET* aOriginal ) const
648 {
649  if( !aModified.IsSelfIntersecting() )
650  {
651  m_statusPopup->Hide();
652  return true;
653  }
654 
655  if( m_statusPopup )
656  {
657  wxPoint p = wxGetMousePosition() + wxPoint( 20, 20 );
658  m_statusPopup->Move( p );
659  m_statusPopup->Popup( getEditFrame<PCB_BASE_FRAME>() );
660  m_statusPopup->Expire( 1500 );
661  }
662 
663  if( aOriginal )
664  aModified = *aOriginal;
665 
666  return false;
667 }
668 
669 
671 {
672  if( !m_editPoints )
673  return;
674 
675  EDA_ITEM* item = m_editPoints->GetParent();
676 
677  if( !item )
678  return;
679 
680  switch( item->Type() )
681  {
682  case PCB_LINE_T:
683  case PCB_MODULE_EDGE_T:
684  {
685  const DRAWSEGMENT* segment = static_cast<const DRAWSEGMENT*>( item );
686 
687  switch( segment->GetShape() )
688  {
689  case S_SEGMENT:
690  m_editPoints->Point( SEG_START ).SetPosition( segment->GetStart() );
691  m_editPoints->Point( SEG_END ).SetPosition( segment->GetEnd() );
692  break;
693 
694  case S_ARC:
695  m_editPoints->Point( ARC_CENTER ).SetPosition( segment->GetCenter() );
696  m_editPoints->Point( ARC_START).SetPosition( segment->GetArcStart() );
697  m_editPoints->Point( ARC_END ).SetPosition( segment->GetArcEnd() );
698  break;
699 
700  case S_CIRCLE:
701  m_editPoints->Point( CIRC_CENTER ).SetPosition( segment->GetCenter() );
702  m_editPoints->Point( CIRC_END ).SetPosition( segment->GetEnd() );
703  break;
704 
705  case S_POLYGON:
706  {
707  const auto& points = segment->BuildPolyPointsList();
708 
709  if( m_editPoints->PointsSize() != (unsigned) points.size() )
710  {
711  getView()->Remove( m_editPoints.get() );
712  m_editedPoint = nullptr;
713  m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() );
714  getView()->Add( m_editPoints.get() );
715  }
716  else
717  {
718  for( unsigned i = 0; i < points.size(); i++ )
719  m_editPoints->Point( i ).SetPosition( points[i] );
720  }
721  break;
722  }
723 
724  case S_CURVE:
725  m_editPoints->Point( BEZIER_CURVE_START ).SetPosition( segment->GetStart() );
726  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ).SetPosition( segment->GetBezControl1() );
727  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ).SetPosition( segment->GetBezControl2() );
728  m_editPoints->Point( BEZIER_CURVE_END ).SetPosition( segment->GetEnd() );
729  break;
730 
731  default: // suppress warnings
732  break;
733  }
734 
735  break;
736  }
737 
738  case PCB_ZONE_AREA_T:
739  {
740  const ZONE_CONTAINER* zone = static_cast<const ZONE_CONTAINER*>( item );
741  const SHAPE_POLY_SET* outline = zone->Outline();
742 
743  if( m_editPoints->PointsSize() != (unsigned) outline->TotalVertices() )
744  {
745  getView()->Remove( m_editPoints.get() );
746  m_editedPoint = nullptr;
747  m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() );
748  getView()->Add( m_editPoints.get() );
749  }
750  else
751  {
752  for( int i = 0; i < outline->TotalVertices(); ++i )
753  m_editPoints->Point( i ).SetPosition( outline->CVertex( i ) );
754  }
755 
756  break;
757  }
758 
759  case PCB_DIMENSION_T:
760  {
761  const DIMENSION* dimension = static_cast<const DIMENSION*>( item );
762 
763  m_editPoints->Point( DIM_CROSSBARO ).SetPosition( dimension->m_crossBarO );
764  m_editPoints->Point( DIM_CROSSBARF ).SetPosition( dimension->m_crossBarF );
765  m_editPoints->Point( DIM_FEATUREGO ).SetPosition( dimension->m_featureLineGO );
766  m_editPoints->Point( DIM_FEATUREDO ).SetPosition( dimension->m_featureLineDO );
767  break;
768  }
769 
770  default:
771  break;
772  }
773 
774  getView()->Update( m_editPoints.get() );
775 }
776 
777 
779 {
781 
782  if( aPoint )
783  {
784  controls->ForceCursorPosition( true, aPoint->GetPosition() );
785  controls->ShowCursor( true );
786  }
787  else
788  {
789  controls->ShowCursor( false );
790  controls->ForceCursorPosition( false );
791  }
792 
793  m_editedPoint = aPoint;
794 }
795 
796 
797 void POINT_EDITOR::setAltConstraint( bool aEnabled )
798 {
799  if( aEnabled )
800  {
801  EDIT_LINE* line = dynamic_cast<EDIT_LINE*>( m_editedPoint );
802 
803  if( line && m_editPoints->GetParent()->Type() == PCB_ZONE_AREA_T )
804  {
806  }
807  else
808  {
809  // Find a proper constraining point for 45 degrees mode
812  }
813  }
814  else
815  {
816  m_altConstraint.reset();
817  }
818 }
819 
820 
822 {
823  EDA_ITEM* item = m_editPoints->GetParent();
824 
825  switch( item->Type() )
826  {
827  case PCB_LINE_T:
828  case PCB_MODULE_EDGE_T:
829  {
830  const DRAWSEGMENT* segment = static_cast<const DRAWSEGMENT*>( item );
831  {
832  switch( segment->GetShape() )
833  {
834  case S_SEGMENT:
835  return *( m_editPoints->Next( *m_editedPoint ) ); // select the other end of line
836 
837  case S_ARC:
838  case S_CIRCLE:
839  return m_editPoints->Point( CIRC_CENTER );
840 
841  default: // suppress warnings
842  break;
843  }
844  }
845 
846  break;
847  }
848 
849  case PCB_DIMENSION_T:
850  {
851  // Constraint for crossbar
852  if( isModified( m_editPoints->Point( DIM_FEATUREGO ) ) )
853  return m_editPoints->Point( DIM_FEATUREDO );
854 
855  else if( isModified( m_editPoints->Point( DIM_FEATUREDO ) ) )
856  return m_editPoints->Point( DIM_FEATUREGO );
857 
858  else
859  return EDIT_POINT( m_editedPoint->GetPosition() ); // no constraint
860 
861  break;
862  }
863 
864  default:
865  break;
866  }
867 
868  // In any other case we may align item to its original position
869  return m_original;
870 }
871 
872 
874 {
880 }
881 
882 
884 {
885  const auto type = aItem.Type();
886 
887  // Works only for zones and line segments
888  return type == PCB_ZONE_AREA_T ||
889  ( ( type == PCB_LINE_T || type == PCB_MODULE_EDGE_T ) &&
890  ( static_cast<const DRAWSEGMENT&>( aItem ).GetShape() == S_SEGMENT ||
891  static_cast<const DRAWSEGMENT&>( aItem ).GetShape() == S_POLYGON ) );
892 }
893 
894 
896 {
897  if( aSelection.Size() != 1 )
898  return false;
899 
900  const EDA_ITEM* item = aSelection.Front();
901 
902  return ( item != nullptr ) && canAddCorner( *item );
903 }
904 
905 
906 // Finds a corresponding vertex in a polygon set
907 static std::pair<bool, SHAPE_POLY_SET::VERTEX_INDEX>
908 findVertex( SHAPE_POLY_SET& aPolySet, const EDIT_POINT& aPoint )
909 {
910  for( auto it = aPolySet.IterateWithHoles(); it; ++it )
911  {
912  auto vertexIdx = it.GetIndex();
913 
914  if( aPolySet.Vertex( vertexIdx ) == aPoint.GetPosition() )
915  return std::make_pair( true, vertexIdx );
916  }
917 
918  return std::make_pair( false, SHAPE_POLY_SET::VERTEX_INDEX() );
919 }
920 
921 
923 {
924  if( !m_editPoints || !m_editedPoint )
925  return false;
926 
927  EDA_ITEM* item = m_editPoints->GetParent();
928 
929  if( !item || !( item->Type() == PCB_ZONE_AREA_T ||
930  ( ( item->Type() == PCB_MODULE_EDGE_T || item->Type() == PCB_LINE_T ) &&
931  static_cast<DRAWSEGMENT*>( item )->GetShape() == S_POLYGON ) ) )
932  return false;
933 
934  SHAPE_POLY_SET *polyset;
935 
936  if( item->Type() == PCB_ZONE_AREA_T )
937  polyset = static_cast<ZONE_CONTAINER*>( item )->Outline();
938  else
939  polyset = &static_cast<DRAWSEGMENT*>( item )->GetPolyShape();
940 
941  auto vertex = findVertex( *polyset, *m_editedPoint );
942 
943  if( !vertex.first )
944  return false;
945 
946  const auto& vertexIdx = vertex.second;
947 
948  // Check if there are enough vertices so one can be removed without
949  // degenerating the polygon.
950  // The first condition allows one to remove all corners from holes (when
951  // there are only 2 vertices left, a hole is removed).
952  if( vertexIdx.m_contour == 0 && polyset->Polygon( vertexIdx.m_polygon )[vertexIdx.m_contour].PointCount() <= 3 )
953  return false;
954 
955  // Remove corner does not work with lines
956  if( dynamic_cast<EDIT_LINE*>( m_editedPoint ) )
957  return false;
958 
959  return m_editedPoint != NULL;
960 }
961 
962 
964 {
965  if( !m_editPoints )
966  return 0;
967 
968  EDA_ITEM* item = m_editPoints->GetParent();
969  PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
970  const VECTOR2I& cursorPos = getViewControls()->GetCursorPosition();
971 
972  // called without an active edited polygon
973  if( !item || !canAddCorner( *item ) )
974  return 0;
975 
976  DRAWSEGMENT* graphicItem = dynamic_cast<DRAWSEGMENT*>( item );
977  BOARD_COMMIT commit( frame );
978 
979  if( item->Type() == PCB_ZONE_AREA_T ||
980  ( graphicItem && graphicItem->GetShape() == S_POLYGON ) )
981  {
982  unsigned int nearestIdx = 0;
983  unsigned int nextNearestIdx = 0;
984  unsigned int nearestDist = INT_MAX;
985  unsigned int firstPointInContour = 0;
986  SHAPE_POLY_SET* zoneOutline;
987 
988  if( item->Type() == PCB_ZONE_AREA_T )
989  zoneOutline = static_cast<ZONE_CONTAINER*>( item )->Outline();
990  else
991  zoneOutline = &( graphicItem->GetPolyShape() );
992 
993  commit.Modify( item );
994 
995  // Search the best outline segment to add a new corner
996  // and therefore break this segment into two segments
997 
998  // Object to iterate through the corners of the outlines (main contour and its holes)
999  SHAPE_POLY_SET::ITERATOR iterator = zoneOutline->Iterate( 0,
1000  zoneOutline->OutlineCount()-1, /* IterateHoles */ true );
1001  int curr_idx = 0;
1002 
1003  // Iterate through all the corners of the outlines and search the best segment
1004  for( ; iterator; iterator++, curr_idx++ )
1005  {
1006  int jj = curr_idx+1;
1007 
1008  if( iterator.IsEndContour() )
1009  { // We reach the last point of the current contour (main or hole)
1010  jj = firstPointInContour;
1011  firstPointInContour = curr_idx+1; // Prepare next contour analysis
1012  }
1013 
1014  SEG curr_segment( zoneOutline->Vertex( curr_idx ), zoneOutline->Vertex( jj ) );
1015 
1016  unsigned int distance = curr_segment.Distance( cursorPos );
1017 
1018  if( distance < nearestDist )
1019  {
1020  nearestDist = distance;
1021  nearestIdx = curr_idx;
1022  nextNearestIdx = jj;
1023  }
1024  }
1025 
1026  // Find the point on the closest segment
1027  VECTOR2I sideOrigin = zoneOutline->Vertex( nearestIdx );
1028  VECTOR2I sideEnd = zoneOutline->Vertex( nextNearestIdx );
1029  SEG nearestSide( sideOrigin, sideEnd );
1030  VECTOR2I nearestPoint = nearestSide.NearestPoint( cursorPos );
1031 
1032  // Do not add points that have the same coordinates as ones that already belong to polygon
1033  // instead, add a point in the middle of the side
1034  if( nearestPoint == sideOrigin || nearestPoint == sideEnd )
1035  nearestPoint = ( sideOrigin + sideEnd ) / 2;
1036 
1037  zoneOutline->InsertVertex( nextNearestIdx, nearestPoint );
1038 
1039  // We re-hatch the filled zones but not polygons
1040  if( item->Type() == PCB_ZONE_AREA_T )
1041  static_cast<ZONE_CONTAINER*>( item )->Hatch();
1042 
1043 
1044  commit.Push( _( "Add a zone corner" ) );
1045  }
1046 
1047  else if( graphicItem && graphicItem->GetShape() == S_SEGMENT )
1048  {
1049  commit.Modify( graphicItem );
1050 
1051  SEG seg( graphicItem->GetStart(), graphicItem->GetEnd() );
1052  VECTOR2I nearestPoint = seg.NearestPoint( cursorPos );
1053 
1054  // Move the end of the line to the break point..
1055  graphicItem->SetEnd( wxPoint( nearestPoint.x, nearestPoint.y ) );
1056 
1057  // and add another one starting from the break point
1058  DRAWSEGMENT* newSegment;
1059 
1060  if( item->Type() == PCB_MODULE_EDGE_T )
1061  {
1062  EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( graphicItem );
1063  assert( edge->GetParent()->Type() == PCB_MODULE_T );
1064  newSegment = new EDGE_MODULE( *edge );
1065  }
1066  else
1067  {
1068  newSegment = new DRAWSEGMENT( *graphicItem );
1069  }
1070 
1071  newSegment->ClearSelected();
1072  newSegment->SetStart( wxPoint( nearestPoint.x, nearestPoint.y ) );
1073  newSegment->SetEnd( wxPoint( seg.B.x, seg.B.y ) );
1074 
1075  commit.Add( newSegment );
1076  commit.Push( _( "Split segment" ) );
1077  }
1078 
1079  updatePoints();
1080  return 0;
1081 }
1082 
1083 
1085 {
1086  if( !m_editPoints || !m_editedPoint )
1087  return 0;
1088 
1089  EDA_ITEM* item = m_editPoints->GetParent();
1090 
1091  if( !item )
1092  return 0;
1093 
1094  SHAPE_POLY_SET* polygon = nullptr;
1095 
1096  if( item->Type() == PCB_ZONE_AREA_T)
1097  {
1098  auto zone = static_cast<ZONE_CONTAINER*>( item );
1099  polygon = zone->Outline();
1100  }
1101  else if( (item->Type() == PCB_MODULE_EDGE_T ) || ( item->Type() == PCB_LINE_T ) )
1102  {
1103  auto ds = static_cast<DRAWSEGMENT*>( item );
1104 
1105  if( ds->GetShape() == S_POLYGON )
1106  polygon = &ds->GetPolyShape();
1107  }
1108 
1109  if( !polygon )
1110  return 0;
1111 
1112  PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
1113  BOARD_COMMIT commit( frame );
1114  auto vertex = findVertex( *polygon, *m_editedPoint );
1115 
1116  if( vertex.first )
1117  {
1118  const auto& vertexIdx = vertex.second;
1119  auto& outline = polygon->Polygon( vertexIdx.m_polygon )[vertexIdx.m_contour];
1120  bool valid = true;
1121 
1122  if( outline.PointCount() > 3 )
1123  {
1124  // the usual case: remove just the corner when there are >3 vertices
1125  commit.Modify( item );
1126  polygon->RemoveVertex( vertexIdx );
1127  valid = validatePolygon( *polygon );
1128  }
1129  else
1130  {
1131  // either remove a hole or the polygon when there are <= 3 corners
1132  if( vertexIdx.m_contour > 0 )
1133  {
1134  // remove hole
1135  commit.Modify( item );
1136  polygon->RemoveContour( vertexIdx.m_contour );
1137  }
1138  else
1139  {
1141  commit.Remove( item );
1142  }
1143  }
1144 
1145  setEditedPoint( nullptr );
1146 
1147  if( valid )
1148  commit.Push( _( "Remove a zone/polygon corner" ) );
1149  else
1150  commit.Revert();
1151 
1152  // Refresh zone hatching
1153  if( item->Type() == PCB_ZONE_AREA_T)
1154  static_cast<ZONE_CONTAINER*>( item )->Hatch();
1155 
1156  updatePoints();
1157  }
1158 
1159  return 0;
1160 }
1161 
1162 
1164 {
1165  m_refill = true; // zone has been modified outside the point editor tool
1166  updatePoints();
1167  return 0;
1168 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
Class EC_CONVERGING.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
BOARD_ITEM_CONTAINER * GetParent() const
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
TOOL_BASE * FindTool(int aId) const
Function FindTool() Searches for a tool with given ID.
void setTransitions() override
Sets up handlers for various events.
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Returns the index-th vertex in a given hole outline within a given outline
const wxPoint & GetBezControl2() const
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...
virtual void Move(const wxPoint &aMoveVector) override
Function Move move this object.
void updateItem() const
Updates item&#39;s points with edit points.
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:289
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
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...
void addCorner(const VECTOR2I &aPoint)
Adds a new edit point on a zone outline/line.
bool IsMotion() const
Definition: tool_event.h:299
const wxPoint GetCenter() const override
Function GetCenter()
void ClearSelected()
Definition: base_struct.h:234
COMMIT & Add(EDA_ITEM *aItem)
Adds a new item to the model
Definition: commit.h:78
VIEW_CONTROLS class definition.
const VECTOR2D Position() const
Returns mouse cursor position in world coordinates.
Definition: tool_event.h:259
void updateEditedPoint(const TOOL_EVENT &aEvent)
Updates which point is being edited.
Class SELECTION_TOOL.
const VECTOR2D DragOrigin() const
Returns the point where dragging has started.
Definition: tool_event.h:265
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:49
polygon (not yet used for tracks, but could be in microwave apps)
EDA_ITEM * Front() const
Definition: selection.h:152
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
CONST_ITERATOR CIterateWithHoles(int aOutline) const
Class EDIT_LINE.
Definition: edit_points.h:189
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:102
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:375
OPT_TOOL_EVENT Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
int TotalVertices() const
Returns total number of vertices stored in the set.
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:243
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:204
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)
std::unique_ptr< STATUS_TEXT_POPUP > m_statusPopup
Definition: point_editor.h:86
static const TOOL_EVENT ClearedEvent
Event sent after selection is cleared.
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...
int OutlineCount() const
Returns the number of outlines in the set
CIRCLE_POINTS
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.
Class EC_45DEGREE.
static TOOL_ACTION selectionModified
Modified selection notification.
Definition: pcb_actions.h:114
bool removeCornerCondition(const SELECTION &aSelection)
Condition to display "Remove corner" context menu entry.
bool IsEndContour() const
Function IsEndContour.
const wxPoint & GetArcStart() const
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
void PassEvent()
Allows a tool to pass the already handled event to the next tool on the stack.
Definition: tool_manager.h:351
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.
KIGFX::VIEW_CONTROLS * controls() const
Definition: pcb_tool.h:138
class MODULE, a footprint
Definition: typeinfo.h:89
double Angle() const
Function Angle computes the angle of the vector.
Definition: vector2d.h:306
STROKE_T GetShape() const
void SetOrigin(const wxPoint &aOrigin)
Function SetOrigin Sets a new origin of the crossbar line.
Class LSET is a set of PCB_LAYER_IDs.
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
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
const wxPoint & GetOrigin() const
Function GetOrigin.
static TOOL_ACTION pointEditorAddCorner
Break outline (insert additional points to an edge)
Definition: pcb_actions.h:227
static TOOL_ACTION pointEditorRemoveCorner
Removes a corner.
Definition: pcb_actions.h:230
void SetEnd(const wxPoint &aEnd)
Function SetEnd Sets a new end of the crossbar line.
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
Arcs (with rounded ends)
PCB_EDIT_FRAME * frame() const
Definition: pcb_tool.h:139
Class TOOL_EVENT.
Definition: tool_event.h:168
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 Fill(std::vector< ZONE_CONTAINER * > aZones, bool aCheck=false)
Definition: zone_filler.cpp:83
EDIT_POINT get45DegConstrainer() const
Returns a point that should be used as a constrainer for 45 degrees mode.
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
DIMENSION_POINTS
SELECTION & GetSelection()
Function GetSelection()
bool isModified(const EDIT_POINT &aPoint) const
Returns true if aPoint is the currently modified point.
Definition: point_editor.h:112
Class VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (...
static const TOOL_EVENT UnselectedEvent
Event sent after an item is unselected.
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 & GetBezControl1() const
SHAPE_POLY_SET & GetPolyShape()
const SELECTION & selection() const
Definition: pcb_tool.cpp:245
SELECTION_TOOL * m_selectionTool
Selection tool used for obtaining selected items
Definition: point_editor.h:66
Bezier Curve.
All active tools
Definition: tool_event.h:144
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:1538
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:100
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg...
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:41
static const TOOL_EVENT SelectedEvent
Event sent after an item is selected.
void SetStart(const wxPoint &aStart)
void SetSnap(bool aSnap)
Definition: grid_helper.h:72
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:35
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Function NearestPoint()
Definition: seg.h:374
Definition: seg.h:36
virtual VECTOR2I GetPosition() const
Function GetPosition()
Definition: edit_points.h:65
VECTOR2D GetGridPoint(const VECTOR2D &aPoint) const
Function GetGridPoint() For a given point it returns the nearest point belonging to the grid in world...
double GetAngle() const
Common, abstract interface for edit frames.
KIGFX::PCB_VIEW * view() const
Definition: pcb_tool.h:137
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddItem()
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
const wxPoint GetArcEnd() const
static bool canAddCorner(const EDA_ITEM &aItem)
Determine if the tool can currently add a corner to the given item
void Hatch()
Function Hatch computes the hatch lines depending on the hatch parameters and stores it in the zone&#39;s...
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:154
void SetAuxAxes(bool aEnable, const VECTOR2I &aOrigin=VECTOR2I(0, 0), bool aEnableDiagonal=false)
void removeCorner(EDIT_POINT *aPoint)
Removes a corner.
int GetWidth() const
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&#39;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
int Size() const
Returns the number of selected parts.
Definition: selection.h:122
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:345
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
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...
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
wxPoint m_featureLineDO
int Distance(const SEG &aSeg) const
Function Distance()
Definition: seg.h:199
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:245
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.
virtual void ApplyConstraint()
Function ApplyConstraint()
Definition: edit_points.h:159
int modifiedSelection(const TOOL_EVENT &aEvent)
ARC_POINTS
void ClearFilledPolysList()
Function ClearFilledPolysList clears the list of filled polygons.
Definition: class_zone.h:549
static bool addCornerCondition(const SELECTION &aSelection)
Condition to display "Create corner" context menu entry.
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:495
Class GAL is the abstract interface for drawing on a 2D-surface.
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.
void SetBezControl1(const wxPoint &aPoint)
static std::shared_ptr< EDIT_POINTS > Make(EDA_ITEM *aItem, KIGFX::GAL *aGal)
BOARD * board() const
Definition: pcb_tool.h:140
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:97