KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
sch_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) 2019 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
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 "sch_point_editor.h"
26
27#include <functional>
28using namespace std::placeholders;
29
30#include <ee_grid_helper.h>
31#include <tool/tool_manager.h>
32#include <sch_commit.h>
33#include <view/view_controls.h>
35#include <geometry/seg.h>
38#include <tools/sch_actions.h>
40#include <sch_edit_frame.h>
41#include <sch_line.h>
42#include <sch_bitmap.h>
43#include <sch_sheet.h>
44#include <sch_textbox.h>
45#include <sch_table.h>
47
48
49static const std::vector<KICAD_T> pointEditorTypes = { SCH_SHAPE_T,
56
57
58// Few constants to avoid using bare numbers for point indices
60{
62};
63
64
66{
68};
69
70
72{
74};
75
76
78{
80};
81
82
84{
86};
87
89{
91};
92
93
95{
96public:
98 m_line( aLine ),
99 m_screen( aScreen )
100 {
101 }
102
103 void MakePoints( EDIT_POINTS& aPoints ) override
104 {
105 std::pair<EDA_ITEM*, int> connectedStart = { nullptr, STARTPOINT };
106 std::pair<EDA_ITEM*, int> connectedEnd = { nullptr, STARTPOINT };
107
109 {
110 if( test->GetLayer() != LAYER_NOTES )
111 continue;
112
113 if( test == &m_line )
114 continue;
115
116 SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
117
118 if( testLine->GetStartPoint() == m_line.GetStartPoint() )
119 {
120 connectedStart = { testLine, STARTPOINT };
121 }
122 else if( testLine->GetEndPoint() == m_line.GetStartPoint() )
123 {
124 connectedStart = { testLine, ENDPOINT };
125 }
126 else if( testLine->GetStartPoint() == m_line.GetEndPoint() )
127 {
128 connectedEnd = { testLine, STARTPOINT };
129 }
130 else if( testLine->GetEndPoint() == m_line.GetEndPoint() )
131 {
132 connectedEnd = { testLine, ENDPOINT };
133 }
134 }
135
136 aPoints.AddPoint( m_line.GetStartPoint(), connectedStart );
137 aPoints.AddPoint( m_line.GetEndPoint(), connectedEnd );
138 }
139
140 void UpdatePoints( EDIT_POINTS& aPoints ) override
141 {
144 }
145
146 void UpdateItem( const EDIT_POINT& aEditedPoints, EDIT_POINTS& aPoints, COMMIT& aCommit,
147 std::vector<EDA_ITEM*>& aUpdatedItems ) override
148 {
151
152 std::pair<EDA_ITEM*, int> connected = aPoints.Point( LINE_START ).GetConnected();
153
154 if( connected.first )
155 {
156 aCommit.Modify( connected.first, &m_screen );
157 aUpdatedItems.push_back( connected.first );
158
159 if( connected.second == STARTPOINT )
160 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( m_line.GetStartPoint() );
161 else if( connected.second == ENDPOINT )
162 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( m_line.GetStartPoint() );
163 }
164
165 connected = aPoints.Point( LINE_END ).GetConnected();
166
167 if( connected.first )
168 {
169 aCommit.Modify( connected.first, &m_screen );
170 aUpdatedItems.push_back( connected.first );
171
172 if( connected.second == STARTPOINT )
173 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( m_line.GetEndPoint() );
174 else if( connected.second == ENDPOINT )
175 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( m_line.GetEndPoint() );
176 }
177 }
178
179private:
182};
183
184
186{
187public:
189 m_arc( aArc )
190 {
191 wxASSERT( m_arc.GetShape() == SHAPE_T::ARC );
192 }
193
194 void MakePoints( EDIT_POINTS& aPoints ) override
195 {
196 aPoints.AddPoint( m_arc.GetStart() );
197 aPoints.AddPoint( m_arc.GetEnd() );
198 aPoints.AddPoint( m_arc.GetPosition() );
199
200 aPoints.AddIndicatorLine( aPoints.Point( ARC_CENTER ), aPoints.Point( ARC_START ) );
201 aPoints.AddIndicatorLine( aPoints.Point( ARC_CENTER ), aPoints.Point( ARC_END ) );
202 }
203
204 void UpdatePoints( EDIT_POINTS& aPoints ) override
205 {
206 aPoints.Point( ARC_START ).SetPosition( m_arc.GetStart() );
207 aPoints.Point( ARC_END ).SetPosition( m_arc.GetEnd() );
209 }
210
211 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
212 std::vector<EDA_ITEM*>& aUpdatedItems ) override
213 {
214 if( isModified( aEditedPoint, aPoints.Point( ARC_START ) ) )
215
216 {
217 m_arc.SetEditState( 2 );
218 m_arc.CalcEdit( aPoints.Point( ARC_START ).GetPosition() );
219 }
220 else if( isModified( aEditedPoint, aPoints.Point( ARC_END ) ) )
221 {
222 m_arc.SetEditState( 3 );
223 m_arc.CalcEdit( aPoints.Point( ARC_END ).GetPosition() );
224 }
225 else if( isModified( aEditedPoint, aPoints.Point( ARC_CENTER ) ) )
226 {
227 m_arc.SetEditState( 4 );
228 m_arc.CalcEdit( aPoints.Point( ARC_CENTER ).GetPosition() );
229 }
230
231 aUpdatedItems.push_back( &m_arc );
232 }
233private:
235};
236
237
239{
240public:
242 m_bitmap( aBitmap )
243 {}
244
245 void MakePoints( EDIT_POINTS& aPoints ) override
246 {
247 const REFERENCE_IMAGE& refImage = m_bitmap.GetReferenceImage();
248 const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
249 const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
250
251 aPoints.AddPoint( topLeft );
252 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
253 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
254 aPoints.AddPoint( botRight );
255
256 aPoints.AddPoint( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
257 }
258
259 void UpdatePoints( EDIT_POINTS& aPoints ) override
260 {
261 const REFERENCE_IMAGE& refImage = m_bitmap.GetReferenceImage();
262 const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
263 const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
264
265 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
266 aPoints.Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
267 aPoints.Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
268 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
269
270 aPoints.Point( REFIMG_ORIGIN )
271 .SetPosition( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
272 }
273
274 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
275 std::vector<EDA_ITEM*>& aUpdatedItems ) override
276 {
278 const VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
279 const VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
280 const VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
281 const VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
282 const VECTOR2I xfrmOrigin = aPoints.Point( REFIMG_ORIGIN ).GetPosition();
283
284 if( isModified( aEditedPoint, aPoints.Point( REFIMG_ORIGIN ) ) )
285 {
286 // Moving the transform origin
287 // As the other points didn't move, we can get the image extent from them
288 const VECTOR2I newOffset = xfrmOrigin - ( topLeft + botRight ) / 2;
289 refImg.SetTransformOriginOffset( newOffset );
290 }
291 else
292 {
293 const VECTOR2I oldOrigin = refImg.GetPosition() + refImg.GetTransformOriginOffset();
294 const VECTOR2I oldSize = refImg.GetSize();
295 const VECTOR2I pos = refImg.GetPosition();
296
297 OPT_VECTOR2I newCorner;
298 VECTOR2I oldCorner = pos;
299
300 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) ) )
301 {
302 newCorner = topLeft;
303 oldCorner -= oldSize / 2;
304 }
305 else if( isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) ) )
306 {
307 newCorner = topRight;
308 oldCorner -= VECTOR2I( -oldSize.x, oldSize.y ) / 2;
309 }
310 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
311 {
312 newCorner = botLeft;
313 oldCorner -= VECTOR2I( oldSize.x, -oldSize.y ) / 2;
314 }
315 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) ) )
316 {
317 newCorner = botRight;
318 oldCorner += oldSize / 2;
319 }
320
321 if( newCorner )
322 {
323 // Turn in the respective vectors from the origin
324 *newCorner -= xfrmOrigin;
325 oldCorner -= oldOrigin;
326
327 // If we tried to cross the origin, clamp it to stop it
328 if( sign( newCorner->x ) != sign( oldCorner.x )
329 || sign( newCorner->y ) != sign( oldCorner.y ) )
330 {
331 *newCorner = VECTOR2I( 0, 0 );
332 }
333
334 const double newLength = newCorner->EuclideanNorm();
335 const double oldLength = oldCorner.EuclideanNorm();
336
337 double ratio = oldLength > 0 ? ( newLength / oldLength ) : 1.0;
338
339 // Clamp the scaling to a minimum of 50 mils
340 VECTOR2I newSize = oldSize * ratio;
341 double newWidth = std::max( newSize.x, EDA_UNIT_UTILS::Mils2IU( schIUScale, 50 ) );
342 double newHeight = std::max( newSize.y, EDA_UNIT_UTILS::Mils2IU( schIUScale, 50 ) );
343 ratio = std::min( newWidth / oldSize.x, newHeight / oldSize.y );
344
345 // Also handles the origin offset
346 refImg.SetImageScale( refImg.GetImageScale() * ratio );
347 }
348 }
349 aUpdatedItems.push_back( &m_bitmap );
350 }
351
352private:
354};
355
356
358{
359public:
362 m_cell( aCell ),
363 m_screen( aScreen )
364 {
365 }
366
367 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
368 std::vector<EDA_ITEM*>& aUpdatedItems ) override
369 {
370 SCH_TABLE& table = static_cast<SCH_TABLE&>( *m_cell.GetParent() );
371 bool rotated = !m_cell.GetTextAngle().IsHorizontal();
372
373 aCommit.Modify( &table, &m_screen );
374 aUpdatedItems.push_back( &table );
375
376 if( rotated )
377 {
378 if( isModified( aEditedPoint, aPoints.Point( ROW_HEIGHT ) ) )
379 {
380 m_cell.SetEnd( VECTOR2I( m_cell.GetEndX(), aPoints.Point( ROW_HEIGHT ).GetY() ) );
381
382 int colWidth = std::abs( m_cell.GetRectangleHeight() );
383
384 for( int ii = 0; ii < m_cell.GetColSpan() - 1; ++ii )
385 colWidth -= table.GetColWidth( m_cell.GetColumn() + ii );
386
387 table.SetColWidth( m_cell.GetColumn() + m_cell.GetColSpan() - 1, colWidth );
388 }
389 else if( isModified( aEditedPoint, aPoints.Point( COL_WIDTH ) ) )
390 {
391 m_cell.SetEnd( VECTOR2I( aPoints.Point( COL_WIDTH ).GetX(), m_cell.GetEndY() ) );
392
393 int rowHeight = m_cell.GetRectangleWidth();
394
395 for( int ii = 0; ii < m_cell.GetRowSpan() - 1; ++ii )
396 rowHeight -= table.GetRowHeight( m_cell.GetRow() + ii );
397
398 table.SetRowHeight( m_cell.GetRow() + m_cell.GetRowSpan() - 1, rowHeight );
399 }
400 }
401 else
402 {
403 if( isModified( aEditedPoint, aPoints.Point( COL_WIDTH ) ) )
404 {
405 m_cell.SetEnd( VECTOR2I( aPoints.Point( COL_WIDTH ).GetX(), m_cell.GetEndY() ) );
406
407 int colWidth = m_cell.GetRectangleWidth();
408
409 for( int ii = 0; ii < m_cell.GetColSpan() - 1; ++ii )
410 colWidth -= table.GetColWidth( m_cell.GetColumn() + ii );
411
412 table.SetColWidth( m_cell.GetColumn() + m_cell.GetColSpan() - 1, colWidth );
413 }
414 else if( isModified( aEditedPoint, aPoints.Point( ROW_HEIGHT ) ) )
415 {
416 m_cell.SetEnd( VECTOR2I( m_cell.GetEndX(), aPoints.Point( ROW_HEIGHT ).GetY() ) );
417
418 int rowHeight = m_cell.GetRectangleHeight();
419
420 for( int ii = 0; ii < m_cell.GetRowSpan() - 1; ++ii )
421 rowHeight -= table.GetRowHeight( m_cell.GetRow() + ii );
422
423 table.SetRowHeight( m_cell.GetRow() + m_cell.GetRowSpan() - 1, rowHeight );
424 }
425 }
426
427 table.Normalize();
428 }
429
430private:
433};
434
435
437{
438public:
440 m_rect( aRect ),
441 m_frame( aFrame )
442 {
443 }
444
445 static void MakePoints( SCH_SHAPE& aRect, EDIT_POINTS& aPoints )
446 {
447 VECTOR2I topLeft = aRect.GetPosition();
448 VECTOR2I botRight = aRect.GetEnd();
449
450 aPoints.AddPoint( topLeft );
451 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
452 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
453 aPoints.AddPoint( botRight );
454 aPoints.AddPoint( aRect.GetCenter() );
455
456 aPoints.AddLine( aPoints.Point( RECT_TOPLEFT ), aPoints.Point( RECT_TOPRIGHT ) );
457 aPoints.Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_TOP ) ) );
458 aPoints.AddLine( aPoints.Point( RECT_TOPRIGHT ), aPoints.Point( RECT_BOTRIGHT ) );
459 aPoints.Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_RIGHT ) ) );
460 aPoints.AddLine( aPoints.Point( RECT_BOTRIGHT ), aPoints.Point( RECT_BOTLEFT ) );
461 aPoints.Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_BOT ) ) );
462 aPoints.AddLine( aPoints.Point( RECT_BOTLEFT ), aPoints.Point( RECT_TOPLEFT ) );
463 aPoints.Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_LEFT ) ) );
464 }
465
466 static void UpdatePoints( SCH_SHAPE& aRect, EDIT_POINTS& aPoints )
467 {
468 VECTOR2I topLeft = aRect.GetPosition();
469 VECTOR2I botRight = aRect.GetEnd();
470
471 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
472 aPoints.Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
473 aPoints.Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
474 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
475 aPoints.Point( RECT_CENTER ).SetPosition( aRect.GetCenter() );
476 }
477
488 static void PinEditedCorner( const EDIT_POINT& aEditedPoint, const EDIT_POINTS& aPoints,
489 int minWidth, int minHeight, VECTOR2I& topLeft, VECTOR2I& topRight,
490 VECTOR2I& botLeft, VECTOR2I& botRight )
491 {
492 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) ) )
493 {
494 // pin edited point within opposite corner
495 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
496 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
497
498 // push edited point edges to adjacent corners
499 topRight.y = topLeft.y;
500 botLeft.x = topLeft.x;
501 }
502 else if( isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) ) )
503 {
504 // pin edited point within opposite corner
505 topRight.x = std::max( topRight.x, botLeft.x + minWidth );
506 topRight.y = std::min( topRight.y, botLeft.y - minHeight );
507
508 // push edited point edges to adjacent corners
509 topLeft.y = topRight.y;
510 botRight.x = topRight.x;
511 }
512 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
513 {
514 // pin edited point within opposite corner
515 botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
516 botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
517
518 // push edited point edges to adjacent corners
519 botRight.y = botLeft.y;
520 topLeft.x = botLeft.x;
521 }
522 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) ) )
523 {
524 // pin edited point within opposite corner
525 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
526 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
527
528 // push edited point edges to adjacent corners
529 botLeft.y = botRight.y;
530 topRight.x = botRight.x;
531 }
532 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
533 {
534 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
535 }
536 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
537 {
538 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
539 }
540 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
541 {
542 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
543 }
544 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
545 {
546 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
547 }
548 }
549
550 static void UpdateItem( SCH_SHAPE& aRect, const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints )
551 {
552 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
553 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
554 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
555 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
556
557 PinEditedCorner( aEditedPoint, aPoints, schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ),
558 topLeft, topRight, botLeft, botRight );
559
560 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
561 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
562 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
563 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
564 {
565 aRect.SetPosition( topLeft );
566 aRect.SetEnd( botRight );
567 }
568 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
569 {
570 aRect.SetStartY( topLeft.y );
571 }
572 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
573 {
574 aRect.SetStartX( topLeft.x );
575 }
576 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
577 {
578 aRect.SetEndY( botRight.y );
579 }
580 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
581 {
582 aRect.SetEndX( botRight.x );
583 }
584
585 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
586 {
587 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
588 {
589 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
590 }
591 }
592 }
593
594 void MakePoints( EDIT_POINTS& aPoints ) override
595 {
597 MakePoints( m_rect, aPoints );
598 }
599
600 void UpdatePoints( EDIT_POINTS& aPoints ) override
601 {
603 UpdatePoints( m_rect, aPoints );
604 }
605
606 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
607 std::vector<EDA_ITEM*>& aUpdatedItems ) override
608 {
609 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
610 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
611 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
612 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
613
614 PinEditedCorner( aEditedPoint, aPoints, schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ),
615 topLeft, topRight, botLeft, botRight );
616
617 const BOX2I oldBox = BOX2I::ByCorners( m_rect.GetStart(), m_rect.GetEnd() );
618 std::vector<SEG> oldSegs;
619 std::vector<VECTOR2I> moveVecs;
620
621 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
622 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
623 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
624 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
625 {
626 // Corner drags don't update pins. Not only is it an escape hatch to avoid
627 // moving pins, it also avoids tricky problems when the pins "fall off"
628 // the ends of one of the two segments and get either left behind or
629 // "swept up" into the corner.
630 m_rect.SetPosition( topLeft );
631 m_rect.SetEnd( botRight );
632 }
633 else if( isModified( aEditedPoint, aPoints.Point( RECT_CENTER ) ) )
634 {
635 VECTOR2I moveVec = aPoints.Point( RECT_CENTER ).GetPosition() - oldBox.GetCenter();
636 m_rect.Move( moveVec );
637 }
638 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
639 {
641 moveVecs.emplace_back( 0, topLeft.y - oldBox.GetTop() );
642 m_rect.SetStartY( topLeft.y );
643 }
644 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
645 {
647 moveVecs.emplace_back( topLeft.x - oldBox.GetLeft(), 0 );
648 m_rect.SetStartX( topLeft.x );
649 }
650 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
651 {
653 moveVecs.emplace_back( 0, botRight.y - oldBox.GetBottom() );
654 m_rect.SetEndY( botRight.y );
655 }
656 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
657 {
659 moveVecs.emplace_back( botRight.x - oldBox.GetRight(), 0 );
660 m_rect.SetEndX( botRight.x );
661 }
662
663 dragPinsOnEdge( oldSegs, moveVecs, m_rect.GetUnit(), aCommit, aUpdatedItems );
664
665 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
666 {
667 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
668 {
669 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
670 }
671 }
672 }
673
674private:
675 void dragPinsOnEdge( const std::vector<SEG>& aOldEdges, const std::vector<VECTOR2I>& aMoveVecs,
676 int aEdgeUnit, COMMIT& aCommit,
677 std::vector<EDA_ITEM*>& aUpdatedItems ) const
678 {
679 wxCHECK( aOldEdges.size() == aMoveVecs.size(), /* void */ );
680
681 // This only make sense in the symbol editor
683 return;
684
686
687 // And only if the setting is enabled
688 if( !editor.GetSettings()->m_dragPinsAlongWithEdges )
689 return;
690
691 // Adjuting pins on a different unit to a unit-limited shape
692 // seems suspect.
693 wxCHECK( aEdgeUnit == 0 || aEdgeUnit == editor.GetUnit(), /* void */ );
694
695 /*
696 * Get a list of pins on a line segment
697 */
698 const auto getPinsOnSeg =
699 []( LIB_SYMBOL& aSymbol, int aUnit, const SEG& aSeg,
700 bool aIncludeEnds ) -> std::vector<SCH_PIN*>
701 {
702 std::vector<SCH_PIN*> pins;
703
704 for( SCH_PIN* pin : aSymbol.GetPins( aUnit, 0 ) )
705 {
706 // Figure out if the pin "connects" to the line
707 const VECTOR2I pinRootPos = pin->GetPinRoot();
708
709 if( aSeg.Contains( pinRootPos ) )
710 {
711 if( aIncludeEnds || ( pinRootPos != aSeg.A && pinRootPos != aSeg.B ) )
712 {
713 pins.push_back( pin );
714 }
715 }
716 }
717
718 return pins;
719 };
720
721 LIB_SYMBOL* const symbol = editor.GetCurSymbol();
722
723 for( std::size_t i = 0; i < aOldEdges.size(); ++i )
724 {
725 if( aMoveVecs[i] == VECTOR2I( 0, 0 ) || !symbol )
726 continue;
727
728 const std::vector<SCH_PIN*> pins = getPinsOnSeg( *symbol, aEdgeUnit, aOldEdges[i],
729 false );
730
731 for( SCH_PIN* pin : pins )
732 {
733 aCommit.Modify( pin );
734 aUpdatedItems.push_back( pin );
735
736 // Move the pin
737 pin->Move( aMoveVecs[i] );
738 }
739 }
740 }
741
742private:
745};
746
747
749{
750public:
752 m_textbox( aTextbox )
753 {}
754
755 void MakePoints( EDIT_POINTS& aPoints ) override
756 {
759 }
760
761 void UpdatePoints( EDIT_POINTS& aPoints ) override
762 {
763 // point editor works only with rectangles having width and height > 0
764 // Some symbols can have rectangles with width or height < 0
765 // So normalize the size:
768 }
769
770 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
771 std::vector<EDA_ITEM*>& aUpdatedItems ) override
772 {
775 }
776
777private:
779};
780
781
783{
784public:
786 m_sheet( aSheet )
787 {}
788
789 void MakePoints( EDIT_POINTS& aPoints ) override
790 {
791 VECTOR2I topLeft = m_sheet.GetPosition();
792 VECTOR2I botRight = m_sheet.GetPosition() + m_sheet.GetSize();
793
794 aPoints.AddPoint( topLeft );
795 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
796 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
797 aPoints.AddPoint( botRight );
798
799 aPoints.AddLine( aPoints.Point( RECT_TOPLEFT ), aPoints.Point( RECT_TOPRIGHT ) );
800 aPoints.Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_TOP ) ) );
801 aPoints.AddLine( aPoints.Point( RECT_TOPRIGHT ), aPoints.Point( RECT_BOTRIGHT ) );
802 aPoints.Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_RIGHT ) ) );
803 aPoints.AddLine( aPoints.Point( RECT_BOTRIGHT ), aPoints.Point( RECT_BOTLEFT ) );
804 aPoints.Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_BOT ) ) );
805 aPoints.AddLine( aPoints.Point( RECT_BOTLEFT ), aPoints.Point( RECT_TOPLEFT ) );
806 aPoints.Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_LEFT ) ) );
807 }
808
809 void UpdatePoints( EDIT_POINTS& aPoints ) override
810 {
811 VECTOR2I topLeft = m_sheet.GetPosition();
812 VECTOR2I botRight = m_sheet.GetPosition() + m_sheet.GetSize();
813
814 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
815 aPoints.Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
816 aPoints.Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
817 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
818 }
819
820 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
821 std::vector<EDA_ITEM*>& aUpdatedItems ) override
822 {
823 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
824 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
825 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
826 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
827 VECTOR2I sheetNewPos = m_sheet.GetPosition();
828 VECTOR2I sheetNewSize = m_sheet.GetSize();
829
830 bool editedTopRight = isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) );
831 bool editedBotLeft = isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) );
832 bool editedBotRight = isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) );
833
834 if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
835 editedTopRight = true;
836 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
837 editedBotLeft = true;
838
840 aEditedPoint, aPoints, m_sheet.GetMinWidth( editedTopRight || editedBotRight ),
841 m_sheet.GetMinHeight( editedBotLeft || editedBotRight ), topLeft, topRight, botLeft,
842 botRight );
843
844 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
845 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
846 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
847 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
848 {
849 sheetNewPos = topLeft;
850 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, botRight.y - topLeft.y );
851 }
852 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
853 {
854 sheetNewPos = VECTOR2I( m_sheet.GetPosition().x, topLeft.y );
855 sheetNewSize = VECTOR2I( m_sheet.GetSize().x, botRight.y - topLeft.y );
856 }
857 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
858 {
859 sheetNewPos = VECTOR2I( topLeft.x, m_sheet.GetPosition().y );
860 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, m_sheet.GetSize().y );
861 }
862 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
863 {
864 sheetNewSize = VECTOR2I( m_sheet.GetSize().x, botRight.y - topLeft.y );
865 }
866 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
867 {
868 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, m_sheet.GetSize().y );
869 }
870
871 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
872 {
873 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
874 {
875 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
876 }
877 }
878
879 if( m_sheet.GetPosition() != sheetNewPos )
880 m_sheet.SetPositionIgnoringPins( sheetNewPos );
881
882 if( m_sheet.GetSize() != sheetNewSize )
883 m_sheet.Resize( sheetNewSize );
884 }
885
886private:
888};
889
890
892{
893 m_editBehavior = nullptr;
894 m_editPoints = std::make_shared<EDIT_POINTS>( aItem );
895
896 if( !aItem )
897 return;
898
899 // Generate list of edit points based on the item type
900 switch( aItem->Type() )
901 {
902 case SCH_SHAPE_T:
903 {
904 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
905
906 switch( shape->GetShape() )
907 {
908 case SHAPE_T::ARC:
909 m_editBehavior = std::make_unique<ARC_POINT_EDIT_BEHAVIOR>( *shape );
910 break;
911 case SHAPE_T::CIRCLE:
912 m_editBehavior = std::make_unique<EDA_CIRCLE_POINT_EDIT_BEHAVIOR>( *shape );
913 break;
914 case SHAPE_T::RECTANGLE:
915 m_editBehavior = std::make_unique<RECTANGLE_POINT_EDIT_BEHAVIOR>( *shape, *m_frame );
916 break;
917 case SHAPE_T::POLY:
918 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
919 break;
920 case SHAPE_T::BEZIER:
921 m_editBehavior = std::make_unique<EDA_BEZIER_POINT_EDIT_BEHAVIOR>( *shape );
922 break;
923 default:
925 }
926
927 break;
928 }
929 case SCH_RULE_AREA_T:
930 {
931 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
932 // Implemented directly as a polygon
933 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
934 break;
935 }
936 case SCH_TEXTBOX_T:
937 {
938 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( aItem );
939 m_editBehavior = std::make_unique<TEXTBOX_POINT_EDIT_BEHAVIOR>( *textbox );
940 break;
941 }
942 case SCH_TABLECELL_T:
943 {
944 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
945 m_editBehavior = std::make_unique<SCH_TABLECELL_POINT_EDIT_BEHAVIOR>( *cell, *m_frame->GetScreen() );
946 break;
947 }
948 case SCH_SHEET_T:
949 {
950 SCH_SHEET& sheet = static_cast<SCH_SHEET&>( *aItem );
951 m_editBehavior = std::make_unique<SHEET_POINT_EDIT_BEHAVIOR>( sheet );
952 break;
953 }
954 case SCH_BITMAP_T:
955 {
956 SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *aItem );
957 m_editBehavior = std::make_unique<BITMAP_POINT_EDIT_BEHAVIOR>( bitmap );
958 break;
959 }
960 case SCH_LINE_T:
961 {
962 SCH_LINE& line = static_cast<SCH_LINE&>( *aItem );
963 m_editBehavior = std::make_unique<LINE_POINT_EDIT_BEHAVIOR>( line, *m_frame->GetScreen() );
964 break;
965 }
966 default:
967 {
968 m_editPoints.reset();
969 break;
970 }
971 }
972
973 // If we got a behavior, generate the points
974 if( m_editBehavior )
975 {
976 wxCHECK( m_editPoints, /* void */ );
977 m_editBehavior->MakePoints( *m_editPoints );
978 }
979}
980
981
983 SCH_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.PointEditor" ),
984 m_editedPoint( nullptr ),
985 m_inPointEditor( false )
986{
987}
988
989
991{
992 SCH_TOOL_BASE::Reset( aReason );
993
994 m_editPoints.reset();
995 m_editedPoint = nullptr;
996}
997
998
1000{
1002
1003 auto& menu = m_selectionTool->GetToolMenu().GetMenu();
1005 std::bind( &SCH_POINT_EDITOR::addCornerCondition, this, _1 ) );
1007 std::bind( &SCH_POINT_EDITOR::removeCornerCondition, this, _1 ) );
1008
1009 return true;
1010}
1011
1012
1014{
1015 setEditedPoint( nullptr );
1016
1017 return 0;
1018}
1019
1020
1022{
1023 EDIT_POINT* point = m_editedPoint;
1024
1025 if( !m_editPoints )
1026 {
1027 point = nullptr;
1028 }
1029 else if( aEvent.IsMotion() )
1030 {
1031 point = m_editPoints->FindPoint( aEvent.Position(), getView() );
1032 }
1033 else if( aEvent.IsDrag( BUT_LEFT ) )
1034 {
1035 point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
1036 }
1037 else
1038 {
1039 point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition( false ), getView() );
1040 }
1041
1042 if( m_editedPoint != point )
1043 setEditedPoint( point );
1044}
1045
1046
1048{
1049 if( !m_selectionTool )
1050 return 0;
1051
1052 if( m_inPointEditor )
1053 return 0;
1054
1056
1057 if( m_isSymbolEditor )
1058 {
1059 SYMBOL_EDIT_FRAME* editor = getEditFrame<SYMBOL_EDIT_FRAME>();
1060
1061 if( !editor->IsSymbolEditable() || editor->IsSymbolAlias() )
1062 return 0;
1063 }
1064
1065 const SCH_SELECTION& selection = m_selectionTool->GetSelection();
1066
1067 if( selection.Size() != 1 || !selection.Front()->IsType( pointEditorTypes ) )
1068 return 0;
1069
1070 // Wait till drawing tool is done
1071 if( selection.Front()->IsNew() )
1072 return 0;
1073
1074 Activate();
1075
1078 VECTOR2I cursorPos;
1079 KIGFX::VIEW* view = getView();
1080 EDA_ITEM* item = selection.Front();
1081 SCH_COMMIT commit( m_toolMgr );
1082
1083 controls->ShowCursor( true );
1084
1085 makePointsAndBehavior( item );
1086 view->Add( m_editPoints.get() );
1087 setEditedPoint( nullptr );
1088 updateEditedPoint( aEvent );
1089 bool inDrag = false;
1090
1091 // Main loop: keep receiving events
1092 while( TOOL_EVENT* evt = Wait() )
1093 {
1094 if( grid )
1095 {
1096 grid->SetSnap( !evt->Modifier( MD_SHIFT ) );
1097 grid->SetUseGrid( getView()->GetGAL()->GetGridSnapping()
1098 && !evt->DisableGridSnapping() );
1099 }
1100 else
1101 {
1102 // This check is based on the assumption that the grid object must be valid.
1103 // If this assumption is wrong, please fix the code above.
1104 wxCHECK( false, 0 );
1105 }
1106
1107 if( !m_editPoints || evt->IsSelectionEvent() )
1108 break;
1109
1110 if ( !inDrag )
1111 updateEditedPoint( *evt );
1112
1113 if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
1114 {
1115 if( !inDrag )
1116 {
1117 commit.Modify( m_editPoints->GetParent(), m_frame->GetScreen() );
1118
1119 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1120 {
1121 shape->SetFlags( IS_MOVING );
1122 shape->SetHatchingDirty();
1123 shape->UpdateHatching();
1124 }
1125
1126 inDrag = true;
1127 }
1128
1129 bool snap = !evt->DisableGridSnapping();
1130
1131 cursorPos = grid->Align( controls->GetMousePosition(),
1132 GRID_HELPER_GRIDS::GRID_GRAPHICS );
1133 controls->ForceCursorPosition( true, cursorPos );
1134
1135 m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
1136
1137 updateParentItem( snap, commit );
1138 updatePoints();
1139 }
1140 else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
1141 {
1142 if( !commit.Empty() )
1143 commit.Push( _( "Move Point" ) );
1144
1145 controls->SetAutoPan( false );
1146
1147 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1148 {
1149 shape->ClearFlags( IS_MOVING );
1150 shape->SetHatchingDirty();
1151 shape->UpdateHatching();
1152 }
1153
1154 inDrag = false;
1155 }
1156 else if( evt->IsCancelInteractive() || evt->IsActivate() )
1157 {
1158 if( inDrag ) // Restore the last change
1159 {
1160 // Currently we are manually managing the lifetime of the grid
1161 // helpers because there is a bug in the tool stack that adds
1162 // the point editor again when commit.Revert() rebuilds the selection.
1163 // We remove this grid here so the its destructor is called before it
1164 // is added again.
1165 if( grid )
1166 {
1167 delete grid;
1168 grid = nullptr;
1169 }
1170
1171 commit.Revert();
1172 inDrag = false;
1173 break;
1174 }
1175 else if( evt->IsCancelInteractive() )
1176 {
1177 break;
1178 }
1179
1180 if( evt->IsActivate() )
1181 break;
1182 }
1183 else
1184 {
1185 evt->SetPassEvent();
1186 }
1187
1188 controls->SetAutoPan( inDrag );
1189 controls->CaptureCursor( inDrag );
1190 }
1191
1192 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1193 {
1194 shape->ClearFlags( IS_MOVING );
1195 shape->SetHatchingDirty();
1196 shape->UpdateHatching();
1197 }
1198
1199 controls->SetAutoPan( false );
1200 controls->CaptureCursor( false );
1201 setEditedPoint( nullptr );
1202
1203 if( m_editPoints )
1204 {
1205 view->Remove( m_editPoints.get() );
1206
1207 m_editPoints.reset();
1209 }
1210
1211 delete grid;
1212
1213 return 0;
1214}
1215
1216
1217void SCH_POINT_EDITOR::updateParentItem( bool aSnapToGrid, SCH_COMMIT& aCommit ) const
1218{
1219 EDA_ITEM* item = m_editPoints->GetParent();
1220
1221 if( !item )
1222 return;
1223
1224 if( !m_editBehavior )
1225 return;
1226
1227 std::vector<EDA_ITEM*> updatedItems;
1228 m_editBehavior->UpdateItem( *m_editedPoint, *m_editPoints, aCommit, updatedItems );
1229
1230 for( EDA_ITEM* updatedItem : updatedItems )
1231 updateItem( updatedItem, true );
1232
1233 m_frame->SetMsgPanel( item );
1234}
1235
1236
1238{
1239 if( !m_editPoints || !m_editBehavior )
1240 return;
1241
1242 m_editBehavior->UpdatePoints( *m_editPoints );
1243 getView()->Update( m_editPoints.get() );
1244}
1245
1246
1248{
1250
1251 if( aPoint )
1252 {
1253 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1254 controls->ForceCursorPosition( true, aPoint->GetPosition() );
1255 controls->ShowCursor( true );
1256 }
1257 else
1258 {
1259 if( m_frame->ToolStackIsEmpty() )
1260 controls->ShowCursor( false );
1261
1262 controls->ForceCursorPosition( false );
1263 }
1264
1265 m_editedPoint = aPoint;
1266}
1267
1268
1270{
1271 bool isRuleArea = false;
1272
1273 if( m_editPoints )
1274 isRuleArea = m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T;
1275
1277 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T || isRuleArea ) )
1278 {
1279 return false;
1280 }
1281
1282 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1283
1284 if( shape->GetPolyShape().IsEmpty() )
1285 return false;
1286
1287 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1288
1289 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1290 return false;
1291 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1292 return false;
1293
1294 for( const VECTOR2I& pt : poly.CPoints() )
1295 {
1296 if( pt == m_editedPoint->GetPosition() )
1297 return true;
1298 }
1299
1300 return false;
1301}
1302
1303
1305{
1306 if( !m_editPoints
1307 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1308 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1309 {
1310 return false;
1311 }
1312
1313 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1314
1315 if( shape->GetShape() != SHAPE_T::POLY )
1316 return false;
1317
1318 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1319 double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
1320
1321 return shape->HitTest( cursorPos, (int) threshold );
1322}
1323
1324
1326{
1327 if( !m_editPoints
1328 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1329 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1330 {
1331 return 0;
1332 }
1333
1334 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1335 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1336 SCH_COMMIT commit( m_toolMgr );
1337
1338 commit.Modify( shape, m_frame->GetScreen() );
1339
1341 int currentMinDistance = INT_MAX;
1342 int closestLineStart = 0;
1343 unsigned numPoints = poly.GetPointCount();
1344
1345 if( !shape->IsClosed() )
1346 numPoints -= 1;
1347
1348 for( unsigned i = 0; i < numPoints; ++i )
1349 {
1350 SEG seg = poly.GetSegment( i );
1351 int distance = seg.Distance( cursor );
1352
1353 if( distance < currentMinDistance )
1354 {
1355 currentMinDistance = distance;
1356 closestLineStart = i;
1357 }
1358 }
1359
1360 poly.Insert( closestLineStart + 1, cursor );
1361
1362 updateItem( shape, true );
1363 updatePoints();
1364
1365 commit.Push( _( "Add Corner" ) );
1366 return 0;
1367}
1368
1369
1371{
1373 || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1374 {
1375 return 0;
1376 }
1377
1378 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1379 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1380 SCH_COMMIT commit( m_toolMgr );
1381
1382 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1383 return 0;
1384 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1385 return 0;
1386
1387 commit.Modify( shape, m_frame->GetScreen() );
1388
1389 int idx = getEditedPointIndex();
1390 int last = (int) poly.GetPointCount() - 1;
1391
1392 if( idx == 0 && poly.GetPoint( 0 ) == poly.GetPoint( last ) )
1393 {
1394 poly.Remove( idx );
1395 poly.SetPoint( last-1, poly.GetPoint( 0 ) );
1396 }
1397 else
1398 {
1399 poly.Remove( idx );
1400 }
1401
1402 shape->SetHatchingDirty();
1403
1404 setEditedPoint( nullptr );
1405
1406 updateItem( shape, true );
1407 updatePoints();
1408
1409 commit.Push( _( "Remove Corner" ) );
1410 return 0;
1411}
1412
1413
1415{
1416 updatePoints();
1417 return 0;
1418}
1419
1420
1422{
1430}
1431
1432
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:112
static TOOL_ACTION activatePointEditor
Definition: actions.h:266
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
ARC_POINT_EDIT_BEHAVIOR(SCH_SHAPE &aArc)
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
BITMAP_POINT_EDIT_BEHAVIOR(SCH_BITMAP &aBitmap)
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
static constexpr BOX2< VECTOR2I > ByCorners(const VECTOR2I &aCorner1, const VECTOR2I &aCorner2)
Definition: box2.h:70
constexpr const Vec GetCenter() const
Definition: box2.h:230
constexpr coord_type GetLeft() const
Definition: box2.h:228
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr coord_type GetTop() const
Definition: box2.h:229
constexpr coord_type GetBottom() const
Definition: box2.h:222
Represent a set of changes (additions, deletions or modifications) of a data model (e....
Definition: commit.h:74
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
Definition: commit.h:108
bool Empty() const
Definition: commit.h:150
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
EDIT_CONSTRAINT for a EDIT_LINE, that constrains the line to move perpendicular to the line itself.
bool IsHorizontal() const
Definition: eda_angle.h:141
bool IsType(FRAME_T aType) const
The base class for create windows for drawing purpose.
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:96
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:108
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:187
EDA_ITEM * GetParent() const
Definition: eda_item.h:110
bool IsNew() const
Definition: eda_item.h:120
void SetStartX(int x)
Definition: eda_shape.h:191
void SetEndY(int aY)
Definition: eda_shape.h:226
int GetEndX() const
Definition: eda_shape.h:217
int GetRectangleWidth() const
Definition: eda_shape.cpp:419
void SetStartY(int y)
Definition: eda_shape.h:184
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:337
SHAPE_T GetShape() const
Definition: eda_shape.h:168
int GetEndY() const
Definition: eda_shape.h:216
void SetEndX(int aX)
Definition: eda_shape.h:233
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:215
bool IsClosed() const
Definition: eda_shape.cpp:505
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:173
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:219
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:340
int GetRectangleHeight() const
Definition: eda_shape.cpp:405
void SetHatchingDirty()
Definition: eda_shape.h:147
"Standard" table-cell editing behavior.
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:145
virtual void ClearRenderCache()
Definition: eda_text.cpp:658
void SetConstraint(EDIT_CONSTRAINT< EDIT_LINE > *aConstraint)
Set a constraint for and EDIT_POINT.
Definition: edit_points.h:267
EDIT_POINTS is a VIEW_ITEM that manages EDIT_POINTs and EDIT_LINEs and draws them.
Definition: edit_points.h:353
void AddPoint(const EDIT_POINT &aPoint)
Add an EDIT_POINT.
Definition: edit_points.h:390
EDIT_LINE & Line(unsigned int aIndex)
Definition: edit_points.h:521
void AddIndicatorLine(EDIT_POINT &aOrigin, EDIT_POINT &aEnd)
Adds an EDIT_LINE that is shown as an indicator, rather than an editable line (no center point drag,...
Definition: edit_points.h:434
unsigned int LinesSize() const
Return number of stored EDIT_LINEs.
Definition: edit_points.h:542
EDIT_POINT & Point(unsigned int aIndex)
Definition: edit_points.h:511
void AddLine(const EDIT_LINE &aLine)
Adds an EDIT_LINE.
Definition: edit_points.h:410
Represent a single point that can be used for modifying items.
Definition: edit_points.h:48
virtual std::pair< EDA_ITEM *, int > GetConnected() const
Return a connected item record comprising an EDA_ITEM* and a STARTPOINT/ENDPOINT flag.
Definition: edit_points.h:79
int GetY() const
Return Y coordinate of an EDIT_POINT.
Definition: edit_points.h:95
static const int POINT_SIZE
Single point size in pixels.
Definition: edit_points.h:190
virtual void SetPosition(const VECTOR2I &aPosition)
Set new coordinates for an EDIT_POINT.
Definition: edit_points.h:107
virtual VECTOR2I GetPosition() const
Return coordinates of an EDIT_POINT.
Definition: edit_points.h:71
int GetX() const
Return X coordinate of an EDIT_POINT.
Definition: edit_points.h:87
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:241
static const TOOL_EVENT ClearedEvent
Definition: actions.h:339
static const TOOL_EVENT SelectedEvent
Definition: actions.h:337
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:344
static const TOOL_EVENT PointSelectedEvent
Definition: actions.h:336
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:297
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:332
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1673
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:457
Define a library symbol object.
Definition: lib_symbol.h:85
std::vector< SCH_PIN * > GetPins(int aUnit, int aBodyStyle) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:800
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
void UpdateItem(const EDIT_POINT &aEditedPoints, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
LINE_POINT_EDIT_BEHAVIOR(SCH_LINE &aLine, SCH_SCREEN &aScreen)
A helper class interface to manage the edit points for a single item.
static bool isModified(const EDIT_POINT &aEditedPoint, const EDIT_POINT &aPoint)
Checks if two points are the same instance - which means the point is being edited.
static void UpdateItem(SCH_SHAPE &aRect, const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints)
static void UpdatePoints(SCH_SHAPE &aRect, EDIT_POINTS &aPoints)
static void PinEditedCorner(const EDIT_POINT &aEditedPoint, const EDIT_POINTS &aPoints, int minWidth, int minHeight, VECTOR2I &topLeft, VECTOR2I &topRight, VECTOR2I &botLeft, VECTOR2I &botRight)
Update the coordinates of 4 corners of a rectangle, according to constraints and the moved corner.
static void MakePoints(SCH_SHAPE &aRect, EDIT_POINTS &aPoints)
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
RECTANGLE_POINT_EDIT_BEHAVIOR(SCH_SHAPE &aRect, EDA_DRAW_FRAME &aFrame)
void dragPinsOnEdge(const std::vector< SEG > &aOldEdges, const std::vector< VECTOR2I > &aMoveVecs, int aEdgeUnit, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) const
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
void SetTransformOriginOffset(const VECTOR2I &aCenter)
VECTOR2I GetTransformOriginOffset() const
Get the center of scaling, etc, relative to the image center (GetPosition()).
VECTOR2I GetPosition() const
VECTOR2I GetSize() const
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
static TOOL_ACTION pointEditorAddCorner
Definition: sch_actions.h:140
static TOOL_ACTION pointEditorRemoveCorner
Definition: sch_actions.h:141
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:40
REFERENCE_IMAGE & GetReferenceImage()
Definition: sch_bitmap.h:51
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
Definition: sch_commit.cpp:487
virtual void Revert() override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:565
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:167
int GetUnit() const
Definition: sch_item.h:236
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
void SetStartPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:139
VECTOR2I GetEndPoint() const
Definition: sch_line.h:143
VECTOR2I GetStartPoint() const
Definition: sch_line.h:138
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:144
void updatePoints()
Update which point is being edited.
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
void setEditedPoint(EDIT_POINT *aPoint)
Return true if aPoint is the currently modified point.
bool Init() override
Init() is called once upon a registration of the tool.
void updateParentItem(bool aSnapToGrid, SCH_COMMIT &aCommit) const
< Update item's points with edit points.
void updateEditedPoint(const TOOL_EVENT &aEvent)
Clear references to the points.
bool addCornerCondition(const SELECTION &aSelection)
std::unique_ptr< POINT_EDIT_BEHAVIOR > m_editBehavior
EDIT_POINT * m_editedPoint
Re-entrancy guards.
int modifiedSelection(const TOOL_EVENT &aEvent)
int Main(const TOOL_EVENT &aEvent)
int getEditedPointIndex() const
std::shared_ptr< EDIT_POINTS > m_editPoints
Current item-specific edit behavior.
int clearEditedPoints(const TOOL_EVENT &aEvent)
Set the current point being edited. NULL means none.
bool removeCornerCondition(const SELECTION &aSelection)
bool m_inPointEditor
Currently available edit points.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
void makePointsAndBehavior(EDA_ITEM *aItem)
Currently edited point, NULL if there is none.
int removeCorner(const TOOL_EVENT &aEvent)
int addCorner(const TOOL_EVENT &aEvent)
TOOL_ACTION handlers.
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition: sch_screen.h:112
SCH_SELECTION & GetSelection()
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:82
void Move(const VECTOR2I &aOffset) override
Move the item by aMoveVector to a new position.
Definition: sch_shape.cpp:80
void SetEditState(int aState)
Definition: sch_shape.h:90
VECTOR2I GetCenter() const
Definition: sch_shape.h:84
void Normalize()
Definition: sch_shape.cpp:86
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: sch_shape.cpp:125
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition: sch_shape.h:88
VECTOR2I GetPosition() const override
Definition: sch_shape.h:81
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:47
void SetPositionIgnoringPins(const VECTOR2I &aPosition)
Definition: sch_sheet.cpp:883
int GetMinWidth(bool aFromLeft) const
Return the minimum width of the sheet based on the widths of the sheet pin text.
Definition: sch_sheet.cpp:519
VECTOR2I GetSize() const
Definition: sch_sheet.h:118
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:415
int GetMinHeight(bool aFromTop) const
Return the minimum height that the sheet can be resized based on the sheet pin positions.
Definition: sch_sheet.cpp:553
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:996
SCH_TABLECELL_POINT_EDIT_BEHAVIOR(SCH_TABLECELL &aCell, SCH_SCREEN &aScreen)
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
int GetColSpan() const
Definition: sch_tablecell.h:59
int GetRowSpan() const
Definition: sch_tablecell.h:62
int GetColumn() const
int GetRow() const
A foundation class for a tool operating on a schematic or symbol.
Definition: sch_tool_base.h:49
void updateItem(EDA_ITEM *aItem, bool aUpdateRTree) const
Similar to getView()->Update(), but handles items that are redrawn by their parents and updating the ...
bool Init() override
Init() is called once upon a registration of the tool.
Definition: sch_tool_base.h:65
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
Definition: sch_tool_base.h:85
SCH_SELECTION_TOOL * m_selectionTool
Definition: seg.h:42
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
Definition: seg.cpp:434
EDA_ITEM * Front() const
Definition: selection.h:172
int Size() const
Returns the number of selected parts.
Definition: selection.h:116
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
virtual const VECTOR2I GetPoint(int aIndex) const override
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
virtual size_t GetPointCount() const override
virtual const SEG GetSegment(int aIndex) const override
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
void Insert(size_t aVertex, const VECTOR2I &aP)
const std::vector< VECTOR2I > & CPoints() const
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
SHEET_POINT_EDIT_BEHAVIOR(SCH_SHEET &aSheet)
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
The symbol library editor main window.
A textbox is edited as a rectnagle when it is orthogonally aligned.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
TEXTBOX_POINT_EDIT_BEHAVIOR(SCH_TEXTBOX &aTextbox)
bool ToolStackIsEmpty()
Definition: tools_holder.h:125
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:44
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:220
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:38
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
Generic, UI-independent tool event.
Definition: tool_event.h:168
bool DisableGridSnapping() const
Definition: tool_event.h:368
const VECTOR2D Position() const
Return mouse cursor position in world coordinates.
Definition: tool_event.h:290
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:312
const VECTOR2D DragOrigin() const
Return the point where dragging has started.
Definition: tool_event.h:296
bool IsMotion() const
Definition: tool_event.h:327
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
TOOL_MENU & GetToolMenu()
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
void Activate()
Run the tool.
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:283
#define _(s)
#define ENDPOINT
ends. (Used to support dragging.)
#define IS_MOVING
Item being moved.
#define STARTPOINT
When a line is selected, these flags indicate which.
@ FRAME_SCH_SYMBOL_EDITOR
Definition: frame_type.h:35
@ LAYER_NOTES
Definition: layer_ids.h:456
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:96
constexpr int Mils2IU(const EDA_IU_SCALE &aIuScale, int mils)
Definition: eda_units.h:166
std::vector< SEG > GetSegsInDirection(const BOX2I &aBox, DIRECTION_45::Directions aDir)
Get the segments of a box that are in the given direction.
Definition: shape_utils.cpp:93
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:393
@ RECT_RIGHT
@ RECT_LEFT
@ RECT_BOT
@ RECT_TOP
@ RECT_CENTER
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
RECTANGLE_POINTS
@ RECT_BOTLEFT
@ RECT_TOPLEFT
@ RECT_TOPRIGHT
@ RECT_CENTER
@ RECT_BOTRIGHT
RECTANGLE_LINES
@ RECT_RIGHT
@ RECT_LEFT
@ RECT_BOT
@ RECT_TOP
TABLECELL_POINTS
@ ROW_HEIGHT
@ COL_WIDTH
static const std::vector< KICAD_T > pointEditorTypes
LINE_POINTS
@ LINE_START
@ LINE_END
REFIMAGE_POINTS
@ REFIMG_ORIGIN
ARC_POINTS
@ ARC_START
@ ARC_END
@ ARC_CENTER
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
Utility functions for working with shapes.
constexpr int MilsToIU(int mils) const
Definition: base_units.h:95
@ MD_SHIFT
Definition: tool_event.h:143
@ BUT_LEFT
Definition: tool_event.h:132
@ SCH_LINE_T
Definition: typeinfo.h:163
@ SCH_TABLECELL_T
Definition: typeinfo.h:166
@ SCH_SHEET_T
Definition: typeinfo.h:175
@ SCH_SHAPE_T
Definition: typeinfo.h:149
@ SCH_RULE_AREA_T
Definition: typeinfo.h:170
@ SCH_ITEM_LOCATE_GRAPHIC_LINE_T
Definition: typeinfo.h:188
@ SCH_BITMAP_T
Definition: typeinfo.h:164
@ SCH_TEXTBOX_T
Definition: typeinfo.h:152
constexpr int sign(T val)
Definition: util.h:159
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695