KiCad PCB EDA Suite
point_editor.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013-2019 CERN
5  * @author Maciej Suminski <maciej.suminski@cern.ch>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <functional>
26 using namespace std::placeholders;
27 #include <tool/tool_manager.h>
28 #include <view/view_controls.h>
30 #include <geometry/seg.h>
31 #include <confirm.h>
32 #include "pcb_actions.h"
33 #include "selection_tool.h"
34 #include "point_editor.h"
35 #include "grid_helper.h"
36 #include <board_commit.h>
37 #include <bitmaps.h>
38 #include <status_popup.h>
39 #include <pcb_edit_frame.h>
40 #include <class_edge_mod.h>
41 #include <class_dimension.h>
42 #include <class_zone.h>
45 
46 // Few constants to avoid using bare numbers for point indices
48 {
50 };
51 
53 {
55 };
56 
58 {
60 };
61 
63 {
68 };
69 
71 {
76 };
77 
79 {
80 private:
81 
82  static void buildForPolyOutline( std::shared_ptr<EDIT_POINTS> points,
83  const SHAPE_POLY_SET* aOutline, KIGFX::GAL* aGal )
84  {
85 
86  int cornersCount = aOutline->TotalVertices();
87 
88  for( auto iterator = aOutline->CIterateWithHoles(); iterator; iterator++ )
89  {
90  points->AddPoint( *iterator );
91 
92  if( iterator.IsEndContour() )
93  points->AddBreak();
94  }
95 
96  // Lines have to be added after creating edit points,
97  // as they use EDIT_POINT references
98  for( int i = 0; i < cornersCount - 1; ++i )
99  {
100  if( points->IsContourEnd( i ) )
101  {
102  points->AddLine( points->Point( i ),
103  points->Point( points->GetContourStartIdx( i ) ) );
104  }
105  else
106  {
107  points->AddLine( points->Point( i ), points->Point( i + 1 ) );
108  }
109 
110  points->Line( i ).SetConstraint( new EC_SNAPLINE( points->Line( i ),
111  std::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) );
112  }
113 
114  // The last missing line, connecting the last and the first polygon point
115  points->AddLine( points->Point( cornersCount - 1 ),
116  points->Point( points->GetContourStartIdx( cornersCount - 1 ) ) );
117 
118  points->Line( points->LinesSize() - 1 ).SetConstraint(
119  new EC_SNAPLINE( points->Line( points->LinesSize() - 1 ),
120  std::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) );
121  }
122 
123 public:
124  static std::shared_ptr<EDIT_POINTS> Make( EDA_ITEM* aItem, KIGFX::GAL* aGal )
125  {
126  std::shared_ptr<EDIT_POINTS> points = std::make_shared<EDIT_POINTS>( aItem );
127 
128  if( !aItem )
129  return points;
130 
131  // Generate list of edit points basing on the item type
132  switch( aItem->Type() )
133  {
134  case PCB_LINE_T:
135  case PCB_MODULE_EDGE_T:
136  {
137  const DRAWSEGMENT* segment = static_cast<const DRAWSEGMENT*>( aItem );
138 
139  switch( segment->GetShape() )
140  {
141  case S_SEGMENT:
142  points->AddPoint( segment->GetStart() );
143  points->AddPoint( segment->GetEnd() );
144  break;
145 
146  case S_ARC:
147  points->AddPoint( segment->GetCenter() );
148  points->AddPoint( segment->GetArcStart() );
149  points->AddPoint( segment->GetArcMid() );
150  points->AddPoint( segment->GetArcEnd() );
151 
152  // Set constraints
153  // Arc end has to stay at the same radius as the start
154  points->Point( ARC_END ).SetConstraint( new EC_CIRCLE( points->Point( ARC_END ),
155  points->Point( ARC_CENTER ),
156  points->Point( ARC_START ) ) );
157 
158  points->Point( ARC_MID ).SetConstraint( new EC_LINE( points->Point( ARC_MID ),
159  points->Point( ARC_CENTER ) ) );
160  break;
161 
162  case S_CIRCLE:
163  points->AddPoint( segment->GetCenter() );
164  points->AddPoint( segment->GetEnd() );
165 
166  break;
167 
168  case S_POLYGON:
169  buildForPolyOutline( points, &segment->GetPolyShape(), aGal );
170  break;
171 
172  case S_CURVE:
173  points->AddPoint( segment->GetStart() );
174  points->AddPoint( segment->GetBezControl1() );
175  points->AddPoint( segment->GetBezControl2() );
176  points->AddPoint( segment->GetEnd() );
177  break;
178 
179  default: // suppress warnings
180  break;
181  }
182 
183  break;
184  }
185 
187  case PCB_ZONE_AREA_T:
188  {
189  auto zone = static_cast<const ZONE_CONTAINER*>( aItem );
190  buildForPolyOutline( points, zone->Outline(), aGal );
191  break;
192  }
193 
194  case PCB_DIMENSION_T:
195  {
196  const DIMENSION* dimension = static_cast<const DIMENSION*>( aItem );
197 
198  points->AddPoint( dimension->m_crossBarO );
199  points->AddPoint( dimension->m_crossBarF );
200  points->AddPoint( dimension->m_featureLineGO );
201  points->AddPoint( dimension->m_featureLineDO );
202 
203  // Dimension height setting - edit points should move only along the feature lines
204  points->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARO ),
205  points->Point( DIM_FEATUREGO ) ) );
206  points->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARF ),
207  points->Point( DIM_FEATUREDO ) ) );
208 
209  break;
210  }
211 
212  default:
213  points.reset();
214  break;
215  }
216 
217  return points;
218  }
219 
220 private:
222 };
223 
224 
226  PCB_TOOL_BASE( "pcbnew.PointEditor" ),
227  m_selectionTool( NULL ),
228  m_editedPoint( NULL ),
229  m_original( VECTOR2I( 0, 0 ) ),
230  m_altConstrainer( VECTOR2I( 0, 0 ) ),
231  m_refill( false )
232 {
233 }
234 
235 
237 {
238  m_refill = false;
239  m_editPoints.reset();
240  m_altConstraint.reset();
241  getViewControls()->SetAutoPan( false );
242 
243  m_statusPopup.reset( new STATUS_TEXT_POPUP( getEditFrame<PCB_BASE_EDIT_FRAME>() ) );
244  m_statusPopup->SetTextColor( wxColour( 255, 0, 0 ) );
245  m_statusPopup->SetText( _( "Self-intersecting polygons are not allowed." ) );
246 }
247 
248 
250 {
251  // Find the selection tool, so they can cooperate
253 
254  wxASSERT_MSG( m_selectionTool, _( "pcbnew.InteractiveSelection tool is not available" ) );
255 
256  auto& menu = m_selectionTool->GetToolMenu().GetMenu();
259  std::bind( &POINT_EDITOR::removeCornerCondition, this, _1 ) );
260 
261  return true;
262 }
263 
264 
266 {
267  EDIT_POINT* point;
268 
269  if( aEvent.IsMotion() )
270  {
271  point = m_editPoints->FindPoint( aEvent.Position(), getView() );
272  }
273  else if( aEvent.IsDrag( BUT_LEFT ) )
274  {
275  point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
276  }
277  else
278  {
279  point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition(), getView() );
280  }
281 
282  if( m_editedPoint != point )
283  setEditedPoint( point );
284 }
285 
286 
288 {
289  if( !m_selectionTool )
290  return 0;
291 
293 
294  if( selection.Size() != 1 || selection.Front()->GetEditFlags() )
295  return 0;
296 
297  Activate();
298 
300  KIGFX::VIEW* view = getView();
301  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
302 
303  controls->ShowCursor( true );
304 
305  GRID_HELPER grid( editFrame );
306  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
307 
308  if( !item )
309  return 0;
310 
311  m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() );
312 
313  if( !m_editPoints )
314  return 0;
315 
316  view->Add( m_editPoints.get() );
317  setEditedPoint( nullptr );
318  updateEditedPoint( aEvent );
319  m_refill = false;
320  bool inDrag = false;
321 
322  BOARD_COMMIT commit( editFrame );
323  LSET snapLayers = item->GetLayerSet();
324 
325  if( item->Type() == PCB_DIMENSION_T )
326  snapLayers = LSET::AllLayersMask();
327 
328  // Main loop: keep receiving events
329  while( TOOL_EVENT* evt = Wait() )
330  {
331  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
332  grid.SetUseGrid( !evt->Modifier( MD_ALT ) );
333  controls->SetSnapping( !evt->Modifier( MD_ALT ) );
334 
335  if( !m_editPoints || evt->IsSelectionEvent() )
336  break;
337 
338  if ( !inDrag )
339  updateEditedPoint( *evt );
340 
341  if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
342  {
343  if( !inDrag )
344  {
345  commit.StageItems( selection, CHT_MODIFY );
346 
347  controls->ForceCursorPosition( false );
348  m_original = *m_editedPoint; // Save the original position
349  controls->SetAutoPan( true );
350  inDrag = true;
351  grid.SetAuxAxes( true, m_original.GetPosition() );
352  }
353 
354  //TODO: unify the constraints to solve simultaneously instead of sequentially
355  m_editedPoint->SetPosition( grid.BestSnapAnchor( evt->Position(),
356  snapLayers, { item } ) );
357 
358  // The alternative constraint limits to 45°
359  bool enableAltConstraint = !!evt->Modifier( MD_CTRL );
360 
361  if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint
362  setAltConstraint( enableAltConstraint );
363 
364  if( m_altConstraint )
365  m_altConstraint->Apply();
366  else
368 
370  snapLayers, { item } ) );
371 
372  updateItem();
373  updatePoints();
374  }
375 
376  else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
377  {
378  controls->SetAutoPan( false );
379  setAltConstraint( false );
380 
381  commit.Push( _( "Drag a corner" ) );
382  inDrag = false;
383  m_refill = true;
384  }
385 
386  else if( evt->IsCancelInteractive() || evt->IsActivate() )
387  {
388  if( inDrag ) // Restore the last change
389  commit.Revert();
390  else if( evt->IsCancelInteractive() )
391  break;
392 
393  if( evt->IsActivate() && !evt->IsMoveTool() )
394  break;
395  }
396 
397  else
398  evt->SetPassEvent();
399  }
400 
401  if( m_editPoints )
402  {
403  view->Remove( m_editPoints.get() );
404 
405  finishItem();
406  m_editPoints.reset();
407  }
408 
409  frame()->UpdateMsgPanel();
410 
411  return 0;
412 }
413 
414 
416 {
417  EDA_ITEM* item = m_editPoints->GetParent();
418 
419  const BOARD_DESIGN_SETTINGS& boardSettings = board()->GetDesignSettings();
420 
421  if( !item )
422  return;
423 
424  switch( item->Type() )
425  {
426  case PCB_LINE_T:
427  case PCB_MODULE_EDGE_T:
428  {
429  DRAWSEGMENT* segment = static_cast<DRAWSEGMENT*>( item );
430  switch( segment->GetShape() )
431  {
432  case S_SEGMENT:
433  if( isModified( m_editPoints->Point( SEG_START ) ) )
434  segment->SetStart( wxPoint( m_editPoints->Point( SEG_START ).GetPosition().x,
435  m_editPoints->Point( SEG_START ).GetPosition().y ) );
436 
437  else if( isModified( m_editPoints->Point( SEG_END ) ) )
438  segment->SetEnd( wxPoint( m_editPoints->Point( SEG_END ).GetPosition().x,
439  m_editPoints->Point( SEG_END ).GetPosition().y ) );
440 
441  break;
442 
443  case S_ARC:
444  {
445  VECTOR2I center = m_editPoints->Point( ARC_CENTER ).GetPosition();
446  VECTOR2I mid = m_editPoints->Point( ARC_MID ).GetPosition();
447  VECTOR2I start = m_editPoints->Point( ARC_START ).GetPosition();
448  VECTOR2I end = m_editPoints->Point( ARC_END ).GetPosition();
449 
450  if( center != segment->GetCenter() )
451  {
452  wxPoint moveVector = wxPoint( center.x, center.y ) - segment->GetCenter();
453  segment->Move( moveVector );
454 
455  m_editPoints->Point( ARC_START ).SetPosition( segment->GetArcStart() );
456  m_editPoints->Point( ARC_END ).SetPosition( segment->GetArcEnd() );
457  m_editPoints->Point( ARC_MID ).SetPosition( segment->GetArcMid() );
458  }
459  else
460  {
461  if( mid != segment->GetArcMid() )
462  {
463  center = GetArcCenter( start, mid, end );
464  segment->SetCenter( wxPoint( center.x, center.y ) );
465  m_editPoints->Point( ARC_CENTER ).SetPosition( center );
466  }
467 
468  segment->SetArcStart( wxPoint( start.x, start.y ) );
469 
470  VECTOR2D startLine = start - center;
471  VECTOR2D endLine = end - center;
472  double newAngle = RAD2DECIDEG( endLine.Angle() - startLine.Angle() );
473 
474  // Adjust the new angle to (counter)clockwise setting
475  bool clockwise = ( segment->GetAngle() > 0 );
476 
477  if( clockwise && newAngle < 0.0 )
478  newAngle += 3600.0;
479  else if( !clockwise && newAngle > 0.0 )
480  newAngle -= 3600.0;
481 
482  segment->SetAngle( newAngle );
483  }
484 
485  break;
486  }
487 
488  case S_CIRCLE:
489  {
490  const VECTOR2I& center = m_editPoints->Point( CIRC_CENTER ).GetPosition();
491  const VECTOR2I& end = m_editPoints->Point( CIRC_END ).GetPosition();
492 
493  if( isModified( m_editPoints->Point( CIRC_CENTER ) ) )
494  {
495  wxPoint moveVector = wxPoint( center.x, center.y ) - segment->GetCenter();
496  segment->Move( moveVector );
497  }
498  else
499  {
500  segment->SetEnd( wxPoint( end.x, end.y ) );
501  }
502 
503  break;
504  }
505 
506  case S_POLYGON:
507  {
508  SHAPE_POLY_SET& outline = segment->GetPolyShape();
509 
510  for( int i = 0; i < outline.TotalVertices(); ++i )
511  outline.Vertex( i ) = m_editPoints->Point( i ).GetPosition();
512 
513  validatePolygon( outline );
514  break;
515  }
516 
517  case S_CURVE:
518  if( isModified( m_editPoints->Point( BEZIER_CURVE_START ) ) )
519  segment->SetStart( wxPoint( m_editPoints->Point( BEZIER_CURVE_START ).GetPosition().x,
520  m_editPoints->Point( BEZIER_CURVE_START ).GetPosition().y ) );
521  else if( isModified( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ) ) )
522  segment->SetBezControl1( wxPoint( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ).GetPosition().x,
523  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ).GetPosition().y ) );
524  else if( isModified( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ) ) )
525  segment->SetBezControl2( wxPoint( m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ).GetPosition().x,
526  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ).GetPosition().y ) );
527  else if( isModified( m_editPoints->Point( BEZIER_CURVE_END ) ) )
528  segment->SetEnd( wxPoint( m_editPoints->Point( BEZIER_CURVE_END ).GetPosition().x,
529  m_editPoints->Point( BEZIER_CURVE_END ).GetPosition().y ) );
530 
531  segment->RebuildBezierToSegmentsPointsList( segment->GetWidth() );
532  break;
533 
534  default: // suppress warnings
535  break;
536  }
537 
538  // Update relative coordinates for module edges
539  if( EDGE_MODULE* edge = dyn_cast<EDGE_MODULE*>( item ) )
540  edge->SetLocalCoord();
541 
542  break;
543  }
544 
546  case PCB_ZONE_AREA_T:
547  {
548  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
549  zone->ClearFilledPolysList();
550  SHAPE_POLY_SET& outline = *zone->Outline();
551 
552  for( int i = 0; i < outline.TotalVertices(); ++i )
553  {
554  if( outline.Vertex( i ) != m_editPoints->Point( i ).GetPosition() )
555  zone->SetNeedRefill( true );
556 
557  outline.Vertex( i ) = m_editPoints->Point( i ).GetPosition();
558  }
559 
560  validatePolygon( outline );
561  zone->Hatch();
562  break;
563  }
564 
565  case PCB_DIMENSION_T:
566  {
567  DIMENSION* dimension = static_cast<DIMENSION*>( item );
568 
569  // Check which point is currently modified and updated dimension's points respectively
570  if( isModified( m_editPoints->Point( DIM_CROSSBARO ) ) )
571  {
572  VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetOrigin() );
573  VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );
574 
575  if( featureLine.Cross( crossBar ) > 0 )
576  dimension->SetHeight( -featureLine.EuclideanNorm(), boardSettings.m_DimensionPrecision );
577  else
578  dimension->SetHeight( featureLine.EuclideanNorm(), boardSettings.m_DimensionPrecision );
579  }
580 
581  else if( isModified( m_editPoints->Point( DIM_CROSSBARF ) ) )
582  {
583  VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetEnd() );
584  VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );
585 
586  if( featureLine.Cross( crossBar ) > 0 )
587  dimension->SetHeight( -featureLine.EuclideanNorm(), boardSettings.m_DimensionPrecision );
588  else
589  dimension->SetHeight( featureLine.EuclideanNorm(), boardSettings.m_DimensionPrecision );
590  }
591 
592  else if( isModified( m_editPoints->Point( DIM_FEATUREGO ) ) )
593  {
594  dimension->SetOrigin( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ),
595  boardSettings.m_DimensionPrecision );
596  m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
597  m_editPoints->Point( DIM_FEATUREGO ) ) );
598  m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
599  m_editPoints->Point( DIM_FEATUREDO ) ) );
600  }
601 
602  else if( isModified( m_editPoints->Point( DIM_FEATUREDO ) ) )
603  {
604  dimension->SetEnd( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ) ,
605  boardSettings.m_DimensionPrecision );
606  m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
607  m_editPoints->Point( DIM_FEATUREGO ) ) );
608  m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
609  m_editPoints->Point( DIM_FEATUREDO ) ) );
610  }
611 
612  break;
613  }
614 
615  default:
616  break;
617  }
618 
619  if( frame() )
620  frame()->SetMsgPanel( item );
621 }
622 
623 
625 {
626  auto item = m_editPoints->GetParent();
627 
628  if( !item )
629  return;
630 
631  if( item->Type() == PCB_ZONE_AREA_T || item->Type() == PCB_MODULE_ZONE_AREA_T )
632  {
633  auto zone = static_cast<ZONE_CONTAINER*>( item );
634 
635  if( zone->IsFilled() && m_refill && zone->NeedRefill() )
636  m_toolMgr->RunAction( PCB_ACTIONS::zoneFill, true, zone );
637  }
638 }
639 
640 
642 {
643  bool valid = !aPoly.IsSelfIntersecting();
644 
645  if( m_statusPopup )
646  {
647  if( valid )
648  {
649  m_statusPopup->Hide();
650  }
651  else
652  {
653  wxPoint p = wxGetMousePosition() + wxPoint( 20, 20 );
654  m_statusPopup->Move( p );
655  m_statusPopup->PopupFor( 1500 );
656  }
657  }
658 
659  return valid;
660 }
661 
662 
664 {
665  if( !m_editPoints )
666  return;
667 
668  EDA_ITEM* item = m_editPoints->GetParent();
669 
670  if( !item )
671  return;
672 
673  switch( item->Type() )
674  {
675  case PCB_LINE_T:
676  case PCB_MODULE_EDGE_T:
677  {
678  const DRAWSEGMENT* segment = static_cast<const DRAWSEGMENT*>( item );
679 
680  switch( segment->GetShape() )
681  {
682  case S_SEGMENT:
683  m_editPoints->Point( SEG_START ).SetPosition( segment->GetStart() );
684  m_editPoints->Point( SEG_END ).SetPosition( segment->GetEnd() );
685  break;
686 
687  case S_ARC:
688  m_editPoints->Point( ARC_CENTER ).SetPosition( segment->GetCenter() );
689  m_editPoints->Point( ARC_START ).SetPosition( segment->GetArcStart() );
690  m_editPoints->Point( ARC_MID ).SetPosition( segment->GetArcMid() );
691  m_editPoints->Point( ARC_END ).SetPosition( segment->GetArcEnd() );
692  break;
693 
694  case S_CIRCLE:
695  m_editPoints->Point( CIRC_CENTER ).SetPosition( segment->GetCenter() );
696  m_editPoints->Point( CIRC_END ).SetPosition( segment->GetEnd() );
697  break;
698 
699  case S_POLYGON:
700  {
701  const auto& points = segment->BuildPolyPointsList();
702 
703  if( m_editPoints->PointsSize() != (unsigned) points.size() )
704  {
705  getView()->Remove( m_editPoints.get() );
706  m_editedPoint = nullptr;
707  m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() );
708  getView()->Add( m_editPoints.get() );
709  }
710  else
711  {
712  for( unsigned i = 0; i < points.size(); i++ )
713  m_editPoints->Point( i ).SetPosition( points[i] );
714  }
715  break;
716  }
717 
718  case S_CURVE:
719  m_editPoints->Point( BEZIER_CURVE_START ).SetPosition( segment->GetStart() );
720  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT1 ).SetPosition( segment->GetBezControl1() );
721  m_editPoints->Point( BEZIER_CURVE_CONTROL_POINT2 ).SetPosition( segment->GetBezControl2() );
722  m_editPoints->Point( BEZIER_CURVE_END ).SetPosition( segment->GetEnd() );
723  break;
724 
725  default: // suppress warnings
726  break;
727  }
728 
729  break;
730  }
731 
733  case PCB_ZONE_AREA_T:
734  {
735  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
736  const SHAPE_POLY_SET* outline = zone->Outline();
737 
738  if( m_editPoints->PointsSize() != (unsigned) outline->TotalVertices() )
739  {
740  getView()->Remove( m_editPoints.get() );
741  m_editedPoint = nullptr;
742  m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() );
743  getView()->Add( m_editPoints.get() );
744  }
745  else
746  {
747  for( int i = 0; i < outline->TotalVertices(); ++i )
748  m_editPoints->Point( i ).SetPosition( outline->CVertex( i ) );
749  }
750 
751  break;
752  }
753 
754  case PCB_DIMENSION_T:
755  {
756  const DIMENSION* dimension = static_cast<const DIMENSION*>( item );
757 
758  m_editPoints->Point( DIM_CROSSBARO ).SetPosition( dimension->m_crossBarO );
759  m_editPoints->Point( DIM_CROSSBARF ).SetPosition( dimension->m_crossBarF );
760  m_editPoints->Point( DIM_FEATUREGO ).SetPosition( dimension->m_featureLineGO );
761  m_editPoints->Point( DIM_FEATUREDO ).SetPosition( dimension->m_featureLineDO );
762  break;
763  }
764 
765  default:
766  break;
767  }
768 
769  getView()->Update( m_editPoints.get() );
770 }
771 
772 
774 {
776 
777  if( aPoint )
778  {
779  frame()->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
780  controls->ForceCursorPosition( true, aPoint->GetPosition() );
781  controls->ShowCursor( true );
782  }
783  else
784  {
785  if( frame()->ToolStackIsEmpty() )
786  controls->ShowCursor( false );
787 
788  controls->ForceCursorPosition( false );
789  }
790 
791  m_editedPoint = aPoint;
792 }
793 
794 
795 void POINT_EDITOR::setAltConstraint( bool aEnabled )
796 {
797  if( aEnabled )
798  {
799  EDIT_LINE* line = dynamic_cast<EDIT_LINE*>( m_editedPoint );
800 
801  if( line &&
802  ( m_editPoints->GetParent()->Type() == PCB_ZONE_AREA_T
803  || m_editPoints->GetParent()->Type() == PCB_MODULE_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 {
875  const auto type = aItem.Type();
876 
877  // Works only for zones and line segments
878  return type == PCB_ZONE_AREA_T || type == PCB_MODULE_ZONE_AREA_T ||
879  ( ( type == PCB_LINE_T || type == PCB_MODULE_EDGE_T ) &&
880  ( static_cast<const DRAWSEGMENT&>( aItem ).GetShape() == S_SEGMENT ||
881  static_cast<const DRAWSEGMENT&>( aItem ).GetShape() == S_POLYGON ) );
882 }
883 
884 
886 {
887  if( aSelection.Size() != 1 )
888  return false;
889 
890  const EDA_ITEM* item = aSelection.Front();
891 
892  return ( item != nullptr ) && canAddCorner( *item );
893 }
894 
895 
896 // Finds a corresponding vertex in a polygon set
897 static std::pair<bool, SHAPE_POLY_SET::VERTEX_INDEX>
898 findVertex( SHAPE_POLY_SET& aPolySet, const EDIT_POINT& aPoint )
899 {
900  for( auto it = aPolySet.IterateWithHoles(); it; ++it )
901  {
902  auto vertexIdx = it.GetIndex();
903 
904  if( aPolySet.Vertex( vertexIdx ) == aPoint.GetPosition() )
905  return std::make_pair( true, vertexIdx );
906  }
907 
908  return std::make_pair( false, SHAPE_POLY_SET::VERTEX_INDEX() );
909 }
910 
911 
913 {
914  if( !m_editPoints || !m_editedPoint )
915  return false;
916 
917  EDA_ITEM* item = m_editPoints->GetParent();
918 
919  if( !item || !( item->Type() == PCB_ZONE_AREA_T || item->Type() == PCB_MODULE_ZONE_AREA_T ||
920  ( ( item->Type() == PCB_MODULE_EDGE_T || item->Type() == PCB_LINE_T ) &&
921  static_cast<DRAWSEGMENT*>( item )->GetShape() == S_POLYGON ) ) )
922  return false;
923 
924  SHAPE_POLY_SET *polyset;
925 
926  if( item->Type() == PCB_ZONE_AREA_T || item->Type() == PCB_MODULE_ZONE_AREA_T )
927  polyset = static_cast<ZONE_CONTAINER*>( item )->Outline();
928  else
929  polyset = &static_cast<DRAWSEGMENT*>( item )->GetPolyShape();
930 
931  auto vertex = findVertex( *polyset, *m_editedPoint );
932 
933  if( !vertex.first )
934  return false;
935 
936  const auto& vertexIdx = vertex.second;
937 
938  // Check if there are enough vertices so one can be removed without
939  // degenerating the polygon.
940  // The first condition allows one to remove all corners from holes (when
941  // there are only 2 vertices left, a hole is removed).
942  if( vertexIdx.m_contour == 0 && polyset->Polygon( vertexIdx.m_polygon )[vertexIdx.m_contour].PointCount() <= 3 )
943  return false;
944 
945  // Remove corner does not work with lines
946  if( dynamic_cast<EDIT_LINE*>( m_editedPoint ) )
947  return false;
948 
949  return m_editedPoint != NULL;
950 }
951 
952 
954 {
955  if( !m_editPoints )
956  return 0;
957 
958  EDA_ITEM* item = m_editPoints->GetParent();
959  PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
960  const VECTOR2I& cursorPos = getViewControls()->GetCursorPosition();
961 
962  // called without an active edited polygon
963  if( !item || !canAddCorner( *item ) )
964  return 0;
965 
966  DRAWSEGMENT* graphicItem = dynamic_cast<DRAWSEGMENT*>( item );
967  BOARD_COMMIT commit( frame );
968 
969  if( item->Type() == PCB_ZONE_AREA_T || item->Type() == PCB_MODULE_ZONE_AREA_T ||
970  ( graphicItem && graphicItem->GetShape() == S_POLYGON ) )
971  {
972  unsigned int nearestIdx = 0;
973  unsigned int nextNearestIdx = 0;
974  unsigned int nearestDist = INT_MAX;
975  unsigned int firstPointInContour = 0;
976  SHAPE_POLY_SET* zoneOutline;
977 
978  if( item->Type() == PCB_ZONE_AREA_T || item->Type() == PCB_MODULE_ZONE_AREA_T )
979  {
980  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
981  zoneOutline = zone->Outline();
982  zone->SetNeedRefill( true );
983  }
984  else
985  zoneOutline = &( graphicItem->GetPolyShape() );
986 
987  commit.Modify( item );
988 
989  // Search the best outline segment to add a new corner
990  // and therefore break this segment into two segments
991 
992  // Object to iterate through the corners of the outlines (main contour and its holes)
993  SHAPE_POLY_SET::ITERATOR iterator = zoneOutline->Iterate( 0,
994  zoneOutline->OutlineCount()-1, /* IterateHoles */ true );
995  int curr_idx = 0;
996 
997  // Iterate through all the corners of the outlines and search the best segment
998  for( ; iterator; iterator++, curr_idx++ )
999  {
1000  int jj = curr_idx+1;
1001 
1002  if( iterator.IsEndContour() )
1003  { // We reach the last point of the current contour (main or hole)
1004  jj = firstPointInContour;
1005  firstPointInContour = curr_idx+1; // Prepare next contour analysis
1006  }
1007 
1008  SEG curr_segment( zoneOutline->Vertex( curr_idx ), zoneOutline->Vertex( jj ) );
1009 
1010  unsigned int distance = curr_segment.Distance( cursorPos );
1011 
1012  if( distance < nearestDist )
1013  {
1014  nearestDist = distance;
1015  nearestIdx = curr_idx;
1016  nextNearestIdx = jj;
1017  }
1018  }
1019 
1020  // Find the point on the closest segment
1021  VECTOR2I sideOrigin = zoneOutline->Vertex( nearestIdx );
1022  VECTOR2I sideEnd = zoneOutline->Vertex( nextNearestIdx );
1023  SEG nearestSide( sideOrigin, sideEnd );
1024  VECTOR2I nearestPoint = nearestSide.NearestPoint( cursorPos );
1025 
1026  // Do not add points that have the same coordinates as ones that already belong to polygon
1027  // instead, add a point in the middle of the side
1028  if( nearestPoint == sideOrigin || nearestPoint == sideEnd )
1029  nearestPoint = ( sideOrigin + sideEnd ) / 2;
1030 
1031  zoneOutline->InsertVertex( nextNearestIdx, nearestPoint );
1032 
1033  // We re-hatch the filled zones but not polygons
1034  if( item->Type() == PCB_ZONE_AREA_T || item->Type() == PCB_MODULE_ZONE_AREA_T )
1035  static_cast<ZONE_CONTAINER*>( item )->Hatch();
1036 
1037 
1038  commit.Push( _( "Add a zone corner" ) );
1039  }
1040 
1041  else if( graphicItem && graphicItem->GetShape() == S_SEGMENT )
1042  {
1043  commit.Modify( graphicItem );
1044 
1045  SEG seg( graphicItem->GetStart(), graphicItem->GetEnd() );
1046  VECTOR2I nearestPoint = seg.NearestPoint( cursorPos );
1047 
1048  // Move the end of the line to the break point..
1049  graphicItem->SetEnd( wxPoint( nearestPoint.x, nearestPoint.y ) );
1050 
1051  // and add another one starting from the break point
1052  DRAWSEGMENT* newSegment;
1053 
1054  if( item->Type() == PCB_MODULE_EDGE_T )
1055  {
1056  EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( graphicItem );
1057  assert( edge->GetParent()->Type() == PCB_MODULE_T );
1058  newSegment = new EDGE_MODULE( *edge );
1059  }
1060  else
1061  {
1062  newSegment = new DRAWSEGMENT( *graphicItem );
1063  }
1064 
1065  newSegment->ClearSelected();
1066  newSegment->SetStart( wxPoint( nearestPoint.x, nearestPoint.y ) );
1067  newSegment->SetEnd( wxPoint( seg.B.x, seg.B.y ) );
1068 
1069  commit.Add( newSegment );
1070  commit.Push( _( "Split segment" ) );
1071  }
1072 
1073  updatePoints();
1074  return 0;
1075 }
1076 
1077 
1079 {
1080  if( !m_editPoints || !m_editedPoint )
1081  return 0;
1082 
1083  EDA_ITEM* item = m_editPoints->GetParent();
1084 
1085  if( !item )
1086  return 0;
1087 
1088  SHAPE_POLY_SET* polygon = nullptr;
1089 
1090  if( item->Type() == PCB_ZONE_AREA_T || item->Type() == PCB_MODULE_ZONE_AREA_T )
1091  {
1092  auto zone = static_cast<ZONE_CONTAINER*>( item );
1093  polygon = zone->Outline();
1094  zone->SetNeedRefill( true );
1095  }
1096  else if( (item->Type() == PCB_MODULE_EDGE_T ) || ( item->Type() == PCB_LINE_T ) )
1097  {
1098  auto ds = static_cast<DRAWSEGMENT*>( item );
1099 
1100  if( ds->GetShape() == S_POLYGON )
1101  polygon = &ds->GetPolyShape();
1102  }
1103 
1104  if( !polygon )
1105  return 0;
1106 
1107  PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
1108  BOARD_COMMIT commit( frame );
1109  auto vertex = findVertex( *polygon, *m_editedPoint );
1110 
1111  if( vertex.first )
1112  {
1113  const auto& vertexIdx = vertex.second;
1114  auto& outline = polygon->Polygon( vertexIdx.m_polygon )[vertexIdx.m_contour];
1115 
1116  if( outline.PointCount() > 3 )
1117  {
1118  // the usual case: remove just the corner when there are >3 vertices
1119  commit.Modify( item );
1120  polygon->RemoveVertex( vertexIdx );
1121  validatePolygon( *polygon );
1122  }
1123  else
1124  {
1125  // either remove a hole or the polygon when there are <= 3 corners
1126  if( vertexIdx.m_contour > 0 )
1127  {
1128  // remove hole
1129  commit.Modify( item );
1130  polygon->RemoveContour( vertexIdx.m_contour );
1131  }
1132  else
1133  {
1135  commit.Remove( item );
1136  }
1137  }
1138 
1139  setEditedPoint( nullptr );
1140 
1141  commit.Push( _( "Remove a zone/polygon corner" ) );
1142 
1143  // Refresh zone hatching
1144  if( item->Type() == PCB_ZONE_AREA_T || item->Type() == PCB_MODULE_ZONE_AREA_T )
1145  static_cast<ZONE_CONTAINER*>( item )->Hatch();
1146 
1147  updatePoints();
1148  }
1149 
1150  return 0;
1151 }
1152 
1153 
1155 {
1156  updatePoints();
1157  return 0;
1158 }
1159 
1160 
1162 {
1169 }
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.
Class EC_CONVERGING.
Class 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
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
const wxPoint GetCenter() const override
Function GetCenter()
void ClearSelected()
Definition: base_struct.h:243
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.
Class SELECTION_TOOL.
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Returns the index-th vertex in a given hole outline within a given outline
Class STATUS_TEXT_POPUP.
Definition: status_popup.h:79
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
Class EDIT_LINE.
Definition: edit_points.h:207
int removeCorner(const TOOL_EVENT &aEvent)
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_BezierPoints vertex list that approximate the Bezier curve by a list of segments Has me...
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h: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:246
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:531
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...
CIRCLE_POINTS
const std::vector< wxPoint > BuildPolyPointsList() const
Build and return the list of corners in a std::vector<wxPoint> It must be used only to convert the SH...
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
void SetCenter(const wxPoint &aCenterPoint)
For arcs and circles:
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
void SetBezControl2(const wxPoint &aPoint)
static TOOL_ACTION zoneFill
Definition: pcb_actions.h:293
Class EC_LINE.
virtual void Remove(VIEW_ITEM *aItem) override
Function Remove() Removes a VIEW_ITEM from the view.
Definition: pcb_view.cpp:74
Class EC_45DEGREE.
void updateItem() const
Updates item's points with edit points.
static const TOOL_EVENT SelectedItemsModified
Definition: actions.h:201
bool removeCornerCondition(const SELECTION &aSelection)
Condition to display "Remove corner" context menu entry.
PCBNEW_SELECTION & GetSelection()
Function GetSelection()
Class EC_CIRCLE.
VECTOR2I & Vertex(int aIndex, int aOutline, int aHole)
Returns the index-th vertex in a given hole outline within a given outline
wxPoint m_featureLineGO
VECTOR2D GetGridPoint(const VECTOR2D &aPoint) const
Function GetGridPoint() For a given point it returns the nearest point belonging to the grid in world...
PCB_BASE_EDIT_FRAME * frame() const
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))
Definition: grid_helper.cpp:93
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:296
Class 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
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:270
ITERATOR IterateWithHoles(int aOutline)
Function IterateWithHoles.
Class SHAPE_POLY_SET.
SEG_POINTS
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
static TOOL_ACTION pointEditorAddCorner
Break outline (insert additional points to an edge)
Definition: pcb_actions.h:207
static TOOL_ACTION pointEditorRemoveCorner
Removes a corner.
Definition: pcb_actions.h:210
Arcs (with rounded ends)
Class 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:374
Class VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (...
const VECTOR2D DragOrigin() const
Returns the point where dragging has started.
Definition: tool_event.h: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:713
const wxPoint & GetArcStart() const
COMMIT & Remove(EDA_ITEM *aItem)
Removes a new item from the model
Definition: commit.h:90
SHAPE_POLY_SET & GetPolyShape()
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:306
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1540
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:99
#define _(s)
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:66
Definition: seg.h:36
EDIT_POINT get45DegConstrainer() const
Returns a point that should be used as a constrainer for 45 degrees mode.
double GetAngle() const
bool validatePolygon(SHAPE_POLY_SET &aModified) const
Validates a polygon and displays a popup warning if invalid.
KIGFX::VIEW_CONTROLS * controls() const
Common, abstract interface for edit frames.
void RemoveVertex(int aGlobalIndex)
Function RemoveVertex deletes the aGlobalIndex-th vertex.
Class ITERATOR_TEMPLATE.
size_t i
Definition: json11.cpp:649
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
static bool canAddCorner(const EDA_ITEM &aItem)
Determine if the tool can currently add a corner to the given item
int Size() const
Returns the number of selected parts.
Definition: selection.h:125
void Hatch()
Function Hatch computes the hatch lines depending on the hatch parameters and stores it in the zone's...
const wxPoint & GetBezControl2() const
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h: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:71
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Class 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
Class VIEW.
Definition: view.h:61
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()
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:339
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
Class EC_SNAPLINE.
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void setEditedPoint(EDIT_POINT *aPoint)
Sets the current point being edited. NULL means none.
static void buildForPolyOutline(std::shared_ptr< EDIT_POINTS > points, const SHAPE_POLY_SET *aOutline, KIGFX::GAL *aGal)
Class DIMENSION.
const VECTOR2D Position() const
Returns mouse cursor position in world coordinates.
Definition: tool_event.h: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...
ARC_POINTS
EDA_ITEM * Front() const
Definition: selection.h:182
void ClearFilledPolysList()
Function ClearFilledPolysList clears the list of filled polygons.
Definition: class_zone.h:542
static bool addCornerCondition(const SELECTION &aSelection)
Condition to display "Create corner" context menu entry.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:210
Class GAL is the abstract interface for drawing on a 2D-surface.
virtual void UpdateMsgPanel()
Redraw the message panel.
Class 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:177