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