KiCad PCB EDA Suite
sch_line.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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 1992-2020 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_painter.h>
26 #include <plotter.h>
27 #include <sch_line.h>
28 #include <sch_edit_frame.h>
30 #include <schematic.h>
31 #include <project/project_file.h>
32 #include <project/net_settings.h>
33 #include <trigo.h>
34 
35 
36 SCH_LINE::SCH_LINE( const wxPoint& pos, int layer ) :
38 {
39  m_start = pos;
40  m_end = pos;
42  m_stroke.SetWidth( 0 );
44  m_stroke.SetColor( COLOR4D::UNSPECIFIED );
45 
46  switch( layer )
47  {
48  default: m_Layer = LAYER_NOTES; break;
49  case LAYER_WIRE: m_Layer = LAYER_WIRE; break;
50  case LAYER_BUS: m_Layer = LAYER_BUS; break;
51  }
52 }
53 
54 
55 SCH_LINE::SCH_LINE( const SCH_LINE& aLine ) :
56  SCH_ITEM( aLine )
57 {
58  m_start = aLine.m_start;
59  m_end = aLine.m_end;
60  m_stroke = aLine.m_stroke;
63 }
64 
65 
67 {
68  return new SCH_LINE( *this );
69 }
70 
71 
72 /*
73  * Conversion between PLOT_DASH_TYPE values and style names displayed
74  */
75 const std::map<PLOT_DASH_TYPE, const char*> lineStyleNames{
76  { PLOT_DASH_TYPE::SOLID, "solid" },
77  { PLOT_DASH_TYPE::DASH, "dashed" },
78  { PLOT_DASH_TYPE::DASHDOT, "dash_dot" },
79  { PLOT_DASH_TYPE::DOT, "dotted" },
80 };
81 
82 
84 {
85  auto resultIt = lineStyleNames.find( aStyle );
86 
87  //legacy behavior is to default to dash if there is no name
88  return resultIt == lineStyleNames.end() ? lineStyleNames.find( PLOT_DASH_TYPE::DASH )->second :
89  resultIt->second;
90 }
91 
92 
93 PLOT_DASH_TYPE SCH_LINE::GetLineStyleByName( const wxString& aStyleName )
94 {
95  PLOT_DASH_TYPE id = PLOT_DASH_TYPE::DEFAULT; // Default style id
96 
97  //find the name by value
98  auto resultIt = std::find_if( lineStyleNames.begin(), lineStyleNames.end(),
99  [aStyleName]( const auto& it ) { return it.second == aStyleName; } );
100 
101  if( resultIt != lineStyleNames.end() )
102  id = resultIt->first;
103 
104  return id;
105 }
106 
107 
108 void SCH_LINE::Move( const wxPoint& aOffset )
109 {
110  if( aOffset != wxPoint( 0, 0 ) )
111  {
112  m_start += aOffset;
113  m_end += aOffset;
114  SetModified();
115  }
116 }
117 
118 
119 void SCH_LINE::MoveStart( const wxPoint& aOffset )
120 {
121  if( aOffset != wxPoint( 0, 0 ) )
122  {
123  m_start += aOffset;
124  SetModified();
125  }
126 }
127 
128 
129 void SCH_LINE::MoveEnd( const wxPoint& aOffset )
130 {
131  if( aOffset != wxPoint( 0, 0 ) )
132  {
133  m_end += aOffset;
134  SetModified();
135  }
136 }
137 
138 
139 #if defined(DEBUG)
140 
141 void SCH_LINE::Show( int nestLevel, std::ostream& os ) const
142 {
143  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
144  << " layer=\"" << m_Layer << '"'
145  << " startIsDangling=\"" << m_startIsDangling
146  << '"' << " endIsDangling=\""
147  << m_endIsDangling << '"' << ">"
148  << " <start" << m_start << "/>"
149  << " <end" << m_end << "/>" << "</"
150  << GetClass().Lower().mb_str() << ">\n";
151 }
152 
153 #endif
154 
155 
156 void SCH_LINE::ViewGetLayers( int aLayers[], int& aCount ) const
157 {
158  aCount = 2;
159  aLayers[0] = m_Layer;
160  aLayers[1] = LAYER_SELECTION_SHADOWS;
161 }
162 
163 
165 {
166  int width = m_stroke.GetWidth() / 2;
167  int extra = m_stroke.GetWidth() & 0x1;
168 
169  int xmin = std::min( m_start.x, m_end.x ) - width;
170  int ymin = std::min( m_start.y, m_end.y ) - width;
171 
172  int xmax = std::max( m_start.x, m_end.x ) + width + extra;
173  int ymax = std::max( m_start.y, m_end.y ) + width + extra;
174 
175  EDA_RECT ret( wxPoint( xmin, ymin ), wxSize( xmax - xmin, ymax - ymin ) );
176 
177  return ret;
178 }
179 
180 
181 double SCH_LINE::GetLength() const
182 {
183  return GetLineLength( m_start, m_end );
184 }
185 
186 
187 void SCH_LINE::SetLineColor( const COLOR4D& aColor )
188 {
189  m_stroke.SetColor( aColor );
190 }
191 
192 
193 void SCH_LINE::SetLineColor( const double r, const double g, const double b, const double a )
194 {
195  COLOR4D newColor(r, g, b, a);
196 
197  if( newColor == COLOR4D::UNSPECIFIED )
198  m_stroke.SetColor( COLOR4D::UNSPECIFIED );
199  else
200  {
201  // Eeschema does not allow alpha channel in colors
202  newColor.a = 1.0;
203  m_stroke.SetColor( newColor );
204  }
205 }
206 
207 
209 {
210  if( m_stroke.GetColor() != COLOR4D::UNSPECIFIED )
211  return m_stroke.GetColor();
212 
213  NETCLASSPTR netclass = NetClass();
214 
215  if( netclass )
216  return netclass->GetSchematicColor();
217 
218  return m_stroke.GetColor();
219 }
220 
221 
223 {
224  if( IsGraphicLine() )
225  return PLOT_DASH_TYPE::DASH;
226 
227  return PLOT_DASH_TYPE::SOLID;
228 }
229 
230 
231 void SCH_LINE::SetLineStyle( const int aStyleId )
232 {
233  SetLineStyle( static_cast<PLOT_DASH_TYPE>( aStyleId ) );
234 }
235 
236 
238 {
239  if( aStyle == GetDefaultStyle() )
241  else
242  m_stroke.SetPlotStyle( aStyle );
243 }
244 
245 
247 {
249  return m_stroke.GetPlotStyle();
250 
251  return GetDefaultStyle();
252 }
253 
254 
256 {
258  return m_stroke.GetPlotStyle();
259 
260  NETCLASSPTR netclass = NetClass();
261 
262  if( netclass )
263  return (PLOT_DASH_TYPE) netclass->GetLineStyle();
264 
265  return GetLineStyle();
266 }
267 
268 
269 void SCH_LINE::SetLineWidth( const int aSize )
270 {
271  m_stroke.SetWidth( aSize );
272 }
273 
274 
276 {
277  NETCLASSPTR netclass = NetClass();
278 
279  switch ( m_Layer )
280  {
281  default:
282  if( m_stroke.GetWidth() > 0 )
283  return m_stroke.GetWidth();
284 
285  if( Schematic() )
287 
288  return DEFAULT_LINE_THICKNESS;
289 
290  case LAYER_WIRE:
291  if( m_stroke.GetWidth() > 0 )
292  return m_stroke.GetWidth();
293 
294  if( netclass )
295  return netclass->GetWireWidth();
296 
297  if( Schematic() )
299 
300  return DEFAULT_WIRE_THICKNESS;
301 
302  case LAYER_BUS:
303  if( m_stroke.GetWidth() > 0 )
304  return m_stroke.GetWidth();
305 
306  if( netclass )
307  return netclass->GetBusWidth();
308 
309  if( Schematic() )
311 
312  return DEFAULT_BUS_THICKNESS;
313  }
314 }
315 
316 
317 void SCH_LINE::Print( RENDER_SETTINGS* aSettings, const wxPoint& offset )
318 {
319  wxDC* DC = aSettings->GetPrintDC();
321 
322  if( color == COLOR4D::UNSPECIFIED )
323  color = aSettings->GetLayerColor( GetLayer() );
324 
325  wxPoint start = m_start;
326  wxPoint end = m_end;
327  int penWidth = std::max( GetPenWidth(), aSettings->GetDefaultPenWidth() );
328 
329  GRLine( nullptr, DC, start.x, start.y, end.x, end.y, penWidth, color,
331 }
332 
333 
334 void SCH_LINE::MirrorX( int aXaxis_position )
335 {
336  MIRROR( m_start.y, aXaxis_position );
337  MIRROR( m_end.y, aXaxis_position );
338 }
339 
340 
341 void SCH_LINE::MirrorY( int aYaxis_position )
342 {
343  MIRROR( m_start.x, aYaxis_position );
344  MIRROR( m_end.x, aYaxis_position );
345 }
346 
347 
348 void SCH_LINE::Rotate( wxPoint aPosition )
349 {
350  RotatePoint( &m_start, aPosition, 900 );
351  RotatePoint( &m_end, aPosition, 900 );
352 }
353 
354 
355 void SCH_LINE::RotateStart( wxPoint aPosition )
356 {
357  RotatePoint( &m_start, aPosition, 900 );
358 }
359 
360 
361 void SCH_LINE::RotateEnd( wxPoint aPosition )
362 {
363  RotatePoint( &m_end, aPosition, 900 );
364 }
365 
366 
367 bool SCH_LINE::IsSameQuadrant( SCH_LINE* aLine, const wxPoint& aPosition )
368 {
369  wxPoint first;
370  wxPoint second;
371 
372  if( m_start == aPosition )
373  first = m_end - aPosition;
374  else if( m_end == aPosition )
375  first = m_start - aPosition;
376  else
377  return false;
378 
379  if( aLine->m_start == aPosition )
380  second = aLine->m_end - aPosition;
381  else if( aLine->m_end == aPosition )
382  second = aLine->m_start - aPosition;
383  else
384  return false;
385 
386  return ( sign( first.x ) == sign( second.x ) && sign( first.y ) == sign( second.y ) );
387 }
388 
389 
391 {
392  wxCHECK_MSG( aLine != NULL && aLine->Type() == SCH_LINE_T, false,
393  wxT( "Cannot test line segment for overlap." ) );
394 
395  wxPoint firstSeg = m_end - m_start;
396  wxPoint secondSeg = aLine->m_end - aLine->m_start;
397 
398  // Use long long here to avoid overflow in calculations
399  return !( (long long) firstSeg.x * secondSeg.y - (long long) firstSeg.y * secondSeg.x );
400 }
401 
402 
403 SCH_LINE* SCH_LINE::MergeOverlap( SCH_SCREEN* aScreen, SCH_LINE* aLine, bool aCheckJunctions )
404 {
405  auto less = []( const wxPoint& lhs, const wxPoint& rhs ) -> bool
406  {
407  if( lhs.x == rhs.x )
408  return lhs.y < rhs.y;
409 
410  return lhs.x < rhs.x;
411  };
412 
413  wxCHECK_MSG( aLine != NULL && aLine->Type() == SCH_LINE_T, NULL,
414  wxT( "Cannot test line segment for overlap." ) );
415 
416  if( this == aLine || GetLayer() != aLine->GetLayer() )
417  return nullptr;
418 
419  auto leftmost_start = aLine->m_start;
420  auto leftmost_end = aLine->m_end;
421 
422  auto rightmost_start = m_start;
423  auto rightmost_end = m_end;
424 
425  // We place the start to the left and below the end of both lines
426  if( leftmost_start != std::min( { leftmost_start, leftmost_end }, less ) )
427  std::swap( leftmost_start, leftmost_end );
428  if( rightmost_start != std::min( { rightmost_start, rightmost_end }, less ) )
429  std::swap( rightmost_start, rightmost_end );
430 
431  // - leftmost is the line that starts farthest to the left
432  // - other is the line that is _not_ leftmost
433  // - rightmost is the line that ends farthest to the right. This may or may not be 'other'
434  // as the second line may be completely covered by the first.
435  if( less( rightmost_start, leftmost_start ) )
436  {
437  std::swap( leftmost_start, rightmost_start );
438  std::swap( leftmost_end, rightmost_end );
439  }
440 
441  wxPoint other_start = rightmost_start;
442  wxPoint other_end = rightmost_end;
443 
444  if( less( rightmost_end, leftmost_end ) )
445  {
446  rightmost_start = leftmost_start;
447  rightmost_end = leftmost_end;
448  }
449 
450  // If we end one before the beginning of the other, no overlap is possible
451  if( less( leftmost_end, other_start ) )
452  {
453  return nullptr;
454  }
455 
456  // Search for a common end:
457  if( ( leftmost_start == other_start ) && ( leftmost_end == other_end ) ) // Trivial case
458  {
459  auto ret = new SCH_LINE( *aLine );
460  ret->SetStartPoint( leftmost_start );
461  ret->SetEndPoint( leftmost_end );
462 
463  if( IsSelected() || aLine->IsSelected() )
464  ret->SetSelected();
465 
466  return ret;
467  }
468 
469  bool colinear = false;
470 
471  /* Test alignment: */
472  if( ( leftmost_start.y == leftmost_end.y ) &&
473  ( other_start.y == other_end.y ) ) // Horizontal segment
474  {
475  colinear = ( leftmost_start.y == other_start.y );
476  }
477  else if( ( leftmost_start.x == leftmost_end.x ) &&
478  ( other_start.x == other_end.x ) ) // Vertical segment
479  {
480  colinear = ( leftmost_start.x == other_start.x );
481  }
482  else
483  {
484  // We use long long here to avoid overflow -- it enforces promotion
485  // The slope of the left-most line is dy/dx. Then we check that the slope from the
486  // left most start to the right most start is the same as well as the slope from the
487  // left most start to right most end.
488  long long dx = leftmost_end.x - leftmost_start.x;
489  long long dy = leftmost_end.y - leftmost_start.y;
490  colinear = ( ( ( other_start.y - leftmost_start.y ) * dx ==
491  ( other_start.x - leftmost_start.x ) * dy ) &&
492  ( ( other_end.y - leftmost_start.y ) * dx ==
493  ( other_end.x - leftmost_start.x ) * dy ) );
494  }
495 
496  if( !colinear )
497  return nullptr;
498 
499  // We either have a true overlap or colinear touching segments. We always want to merge
500  // the former, but the later only get merged if there no junction at the touch point.
501 
502  bool touching = leftmost_end == rightmost_start;
503 
504  if( touching && aCheckJunctions && aScreen->IsJunctionNeeded( leftmost_end ) )
505  return nullptr;
506 
507  // Make a new segment that merges the 2 segments
508  leftmost_end = rightmost_end;
509 
510  auto ret = new SCH_LINE( *aLine );
511  ret->SetStartPoint( leftmost_start );
512  ret->SetEndPoint( leftmost_end );
513 
514  if( IsSelected() || aLine->IsSelected() )
515  ret->SetSelected();
516 
517  return ret;
518 }
519 
520 
521 void SCH_LINE::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
522 {
523  if( IsGraphicLine() )
524  return;
525 
526  if( ( GetLayer() == LAYER_BUS ) || ( GetLayer() == LAYER_WIRE ) )
527  {
529  m_start );
530  aItemList.push_back( item );
531 
533  m_end );
534  aItemList.push_back( item1 );
535  }
536 }
537 
538 
539 bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
540  const SCH_SHEET_PATH* aPath )
541 {
542  bool previousStartState = m_startIsDangling;
543  bool previousEndState = m_endIsDangling;
544 
546 
547  if( GetLayer() == LAYER_WIRE )
548  {
549  for( DANGLING_END_ITEM item : aItemList )
550  {
551  if( item.GetItem() == this )
552  continue;
553 
554  if( item.GetType() == BUS_START_END ||
555  item.GetType() == BUS_END_END ||
556  item.GetType() == BUS_ENTRY_END )
557  continue;
558 
559  if( m_start == item.GetPosition() )
560  m_startIsDangling = false;
561 
562  if( m_end == item.GetPosition() )
563  m_endIsDangling = false;
564 
566  break;
567  }
568  }
569  else if( GetLayer() == LAYER_BUS || IsGraphicLine() )
570  {
571  // Lines on the notes layer and the bus layer cannot be tested for dangling ends.
572  previousStartState = previousEndState = m_startIsDangling = m_endIsDangling = false;
573  }
574 
575  return ( previousStartState != m_startIsDangling ) || ( previousEndState != m_endIsDangling );
576 }
577 
578 
580 {
581  if( m_Layer == LAYER_WIRE || m_Layer == LAYER_BUS )
582  return true;
583 
584  return false;
585 }
586 
587 
588 bool SCH_LINE::CanConnect( const SCH_ITEM* aItem ) const
589 {
590  if( m_Layer == LAYER_WIRE )
591  {
592  switch( aItem->Type() )
593  {
594  case SCH_JUNCTION_T:
595  case SCH_NO_CONNECT_T:
596  case SCH_LABEL_T:
597  case SCH_GLOBAL_LABEL_T:
598  case SCH_HIER_LABEL_T:
600  case SCH_COMPONENT_T:
601  case SCH_SHEET_T:
602  case SCH_SHEET_PIN_T:
603  return true;
604  default:
605  break;
606  }
607  }
608  else if( m_Layer == LAYER_BUS )
609  {
610  switch( aItem->Type() )
611  {
612  case SCH_JUNCTION_T:
613  case SCH_LABEL_T:
614  case SCH_GLOBAL_LABEL_T:
615  case SCH_HIER_LABEL_T:
617  case SCH_SHEET_T:
618  case SCH_SHEET_PIN_T:
619  return true;
620  default:
621  break;
622  }
623  }
624 
625  return aItem->GetLayer() == m_Layer;
626 }
627 
628 
629 std::vector<wxPoint> SCH_LINE::GetConnectionPoints() const
630 {
631  return { m_start, m_end };
632 }
633 
634 
635 void SCH_LINE::GetSelectedPoints( std::vector< wxPoint >& aPoints ) const
636 {
637  if( m_Flags & STARTPOINT )
638  aPoints.push_back( m_start );
639 
640  if( m_Flags & ENDPOINT )
641  aPoints.push_back( m_end );
642 }
643 
644 
645 wxString SCH_LINE::GetSelectMenuText( EDA_UNITS aUnits ) const
646 {
647  wxString txtfmt, orient;
648 
649  if( m_start.x == m_end.x )
650  {
651  switch( m_Layer )
652  {
653  case LAYER_WIRE: txtfmt = _( "Vertical Wire, length %s" ); break;
654  case LAYER_BUS: txtfmt = _( "Vertical Bus, length %s" ); break;
655  default: txtfmt = _( "Vertical Graphic Line, length %s" ); break;
656  }
657  }
658  else if( m_start.y == m_end.y )
659  {
660  switch( m_Layer )
661  {
662  case LAYER_WIRE: txtfmt = _( "Horizontal Wire, length %s" ); break;
663  case LAYER_BUS: txtfmt = _( "Horizontal Bus, length %s" ); break;
664  default: txtfmt = _( "Horizontal Graphic Line, length %s" ); break;
665  }
666  }
667  else
668  {
669  switch( m_Layer )
670  {
671  case LAYER_WIRE: txtfmt = _( "Wire, length %s" ); break;
672  case LAYER_BUS: txtfmt = _( "Bus, length %s" ); break;
673  default: txtfmt = _( "Graphic Line, length %s" ); break;
674  }
675  }
676 
677  return wxString::Format( txtfmt,
679 }
680 
681 
683 {
684  if( m_Layer == LAYER_NOTES )
685  return add_dashed_line_xpm;
686  else if( m_Layer == LAYER_WIRE )
687  return add_line_xpm;
688 
689  return add_bus_xpm;
690 }
691 
692 
693 bool SCH_LINE::operator <( const SCH_ITEM& aItem ) const
694 {
695  if( Type() != aItem.Type() )
696  return Type() < aItem.Type();
697 
698  auto line = static_cast<const SCH_LINE*>( &aItem );
699 
700  if( GetLayer() != line->GetLayer() )
701  return GetLayer() < line->GetLayer();
702 
703  if( GetStartPoint().x != line->GetStartPoint().x )
704  return GetStartPoint().x < line->GetStartPoint().x;
705 
706  if( GetStartPoint().y != line->GetStartPoint().y )
707  return GetStartPoint().y < line->GetStartPoint().y;
708 
709  if( GetEndPoint().x != line->GetEndPoint().x )
710  return GetEndPoint().x < line->GetEndPoint().x;
711 
712  return GetEndPoint().y < line->GetEndPoint().y;
713 }
714 
715 
716 bool SCH_LINE::HitTest( const wxPoint& aPosition, int aAccuracy ) const
717 {
718  // Performance enhancement for connection-building
719  if( aPosition == m_start || aPosition == m_end )
720  return true;
721 
722  // Insure minimum accuracy
723  if( aAccuracy == 0 )
724  aAccuracy = ( GetPenWidth() / 2 ) + 4;
725 
726  return TestSegmentHit( aPosition, m_start, m_end, aAccuracy );
727 }
728 
729 
730 bool SCH_LINE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
731 {
732  if( m_Flags & ( STRUCT_DELETED | SKIP_STRUCT ) )
733  return false;
734 
735  EDA_RECT rect = aRect;
736 
737  if ( aAccuracy )
738  rect.Inflate( aAccuracy );
739 
740  if( aContained )
741  return rect.Contains( m_start ) && rect.Contains( m_end );
742 
743  return rect.Intersects( m_start, m_end );
744 }
745 
746 
748 {
749  SCH_LINE* item = (SCH_LINE*) aItem;
750 
751  std::swap( m_Layer, item->m_Layer );
752 
753  std::swap( m_start, item->m_start );
754  std::swap( m_end, item->m_end );
755  std::swap( m_startIsDangling, item->m_startIsDangling );
756  std::swap( m_endIsDangling, item->m_endIsDangling );
757  std::swap( m_stroke, item->m_stroke );
758 }
759 
760 
761 bool SCH_LINE::doIsConnected( const wxPoint& aPosition ) const
762 {
763  if( m_Layer != LAYER_WIRE && m_Layer != LAYER_BUS )
764  return false;
765 
766  return IsEndPoint( aPosition );
767 }
768 
769 
770 void SCH_LINE::Plot( PLOTTER* aPlotter )
771 {
772  auto* settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( aPlotter->RenderSettings() );
773  int penWidth;
775 
776  if( color == COLOR4D::UNSPECIFIED )
777  color = settings->GetLayerColor( GetLayer() );
778 
779  aPlotter->SetColor( color );
780 
781  switch( m_Layer )
782  {
783  case LAYER_WIRE: penWidth = settings->m_DefaultWireThickness; break;
784  case LAYER_BUS: penWidth = settings->m_DefaultBusThickness; break;
785  default: penWidth = GetPenWidth(); break;
786  }
787 
788  if( m_stroke.GetWidth() != 0 )
789  penWidth = m_stroke.GetWidth();
790 
791  penWidth = std::max( penWidth, settings->GetMinPenWidth() );
792 
793  aPlotter->SetCurrentLineWidth( penWidth );
794  aPlotter->SetDash( GetEffectiveLineStyle() );
795 
796  aPlotter->MoveTo( m_start );
797  aPlotter->FinishTo( m_end );
798 
799  aPlotter->SetDash( PLOT_DASH_TYPE::SOLID );
800 }
801 
802 
803 void SCH_LINE::SetPosition( const wxPoint& aPosition )
804 {
805  m_end = m_end - ( m_start - aPosition );
806  m_start = aPosition;
807 }
808 
809 
811 {
812  wxString msg;
813 
814  switch( GetLayer() )
815  {
816  case LAYER_WIRE: msg = _( "Wire" ); break;
817  case LAYER_BUS: msg = _( "Bus" ); break;
818  default: msg = _( "Graphical" ); break;
819  }
820 
821  aList.push_back( MSG_PANEL_ITEM( _( "Line Type" ), msg, DARKCYAN ) );
822 
824  msg = _( "from netclass" );
825  else
826  msg = GetLineStyleName( GetLineStyle() );
827 
828  aList.push_back( MSG_PANEL_ITEM( _( "Line Style" ), msg, DARKCYAN ) );
829 
830  SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
831 
832  if( frame )
833  {
834  if( SCH_CONNECTION* conn = Connection() )
835  {
836  conn->AppendInfoToMsgPanel( aList );
837 
838  NET_SETTINGS& netSettings = Schematic()->Prj().GetProjectFile().NetSettings();
839  wxString netname = conn->Name();
840  wxString netclassName = netSettings.m_NetClasses.GetDefaultPtr()->GetName();
841 
842  if( netSettings.m_NetClassAssignments.count( netname ) )
843  netclassName = netSettings.m_NetClassAssignments[ netname ];
844 
845  aList.push_back( MSG_PANEL_ITEM( _( "Assigned Netclass" ), netclassName, DARKRED ) );
846  }
847  }
848 }
849 
850 
852 {
853  return ( GetLayer() == LAYER_NOTES );
854 }
855 
856 
857 bool SCH_LINE::IsWire() const
858 {
859  return ( GetLayer() == LAYER_WIRE );
860 }
861 
862 
864 {
865  return m_stroke.GetWidth() == 0 && m_stroke.GetColor() == COLOR4D::UNSPECIFIED
868 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:134
void Rotate(wxPoint aPosition) override
Rotate the item around aPosition 90 degrees in the clockwise direction.
Definition: sch_line.cpp:348
void FinishTo(const wxPoint &pos)
Definition: plotter.h:283
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Add the schematic item end points to aItemList if the item has end points.
Definition: sch_line.cpp:521
static const char * GetLineStyleName(PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:83
int sign(T val)
Definition: util.h:101
SCH_LAYER_ID m_Layer
Definition: sch_item.h:199
void SetModified()
Definition: eda_item.cpp:79
SCH_LINE * MergeOverlap(SCH_SCREEN *aScreen, SCH_LINE *aLine, bool aCheckJunctions)
Check line against aLine to see if it overlaps and merge if it does.
Definition: sch_line.cpp:403
std::map< wxString, wxString > m_NetClassAssignments
Definition: net_settings.h:43
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Definition: base_units.cpp:123
COLOR4D GetLineColor() const
Returns COLOR4D::UNSPECIFIED if a custom color hasn't been set for this line.
Definition: sch_line.cpp:208
void SetWidth(int aWidth)
Definition: sch_item.h:170
Plot settings, and plotting engines (PostScript, Gerber, HPGL and DXF)
wxString GetClass() const override
Function GetClass returns the class name.
Definition: sch_line.h:64
bool IsGraphicLine() const
Returns if the line is a graphic (non electrical line)
Definition: sch_line.cpp:851
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:212
PNG memory record (file in memory).
Definition: bitmap_def.h:29
const BITMAP_OPAQUE add_dashed_line_xpm[1]
wxPoint GetStartPoint() const
Definition: sch_line.h:94
RENDER_SETTINGS Contains all the knowledge about how graphical objects are drawn on any output surfac...
bool IsWire() const
Returns true if the line is a wire.
Definition: sch_line.cpp:857
bool IsSelected() const
Definition: eda_item.h:192
bool IsJunctionNeeded(const wxPoint &aPosition, bool aNew=false)
Test if a junction is required for the items at aPosition on the screen.
Definition: sch_screen.cpp:371
virtual void SetColor(COLOR4D color)=0
const wxString & GetName() const
Definition: netclass.h:96
bool m_endIsDangling
True if end point is not connected.
Definition: sch_line.h:40
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:269
void RotateEnd(wxPoint aPosition)
Definition: sch_line.cpp:361
void MoveStart(const wxPoint &aMoveVector)
Definition: sch_line.cpp:119
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:124
bool IsParallel(SCH_LINE *aLine)
Definition: sch_line.cpp:390
int color
Definition: DXF_plotter.cpp:60
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:113
void Plot(PLOTTER *aPlotter) override
Plot the schematic item to aPlotter.
Definition: sch_line.cpp:770
const COLOR4D & GetLayerColor(int aLayer) const
Function GetLayerColor Returns the color used to draw a layer.
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
Definition: sch_line.cpp:810
NET_SETTINGS & NetSettings()
Definition: project_file.h:92
Schematic editor (Eeschema) main window.
void SetPlotStyle(PLOT_DASH_TYPE aPlotStyle)
Definition: sch_item.h:173
bool CanConnect(const SCH_ITEM *aItem) const override
Definition: sch_line.cpp:588
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
The base class for create windows for drawing purpose.
void ViewGetLayers(int aLayers[], int &aCount) const override
Return the layers the item is drawn on (which may be more than its "home" layer)
Definition: sch_line.cpp:156
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Definition: sch_line.cpp:645
bool Contains(const wxPoint &aPoint) const
Function Contains.
Definition: eda_rect.cpp:57
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
Definition: sch_line.cpp:716
void RotateStart(wxPoint aPosition)
Definition: sch_line.cpp:355
bool UsesDefaultStroke() const
Test if the SCH_LINE object uses the default stroke settings.
Definition: sch_line.cpp:863
void Move(const wxPoint &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition: sch_line.cpp:108
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition: sch_item.cpp:147
bool TestSegmentHit(const wxPoint &aRefPoint, wxPoint aStart, wxPoint aEnd, int aDist)
Test if aRefPoint is with aDistance on the line defined by aStart and aEnd.
Definition: trigo.cpp:129
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:136
NETCLASSPTR NetClass(const SCH_SHEET_PATH *aSheet=nullptr) const
Definition: sch_item.cpp:161
bool IsConnectable() const override
Definition: sch_line.cpp:579
PLOT_DASH_TYPE GetDefaultStyle() const
Definition: sch_line.cpp:222
void SetLineStyle(const PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:237
double a
Alpha component.
Definition: color4d.h:377
void MirrorX(int aXaxis_position) override
Mirror item relative to the X axis about aXaxis_position.
Definition: sch_line.cpp:334
NETCLASSES m_NetClasses
Definition: net_settings.h:39
#define NULL
const std::map< PLOT_DASH_TYPE, const char * > lineStyleNames
Definition: sch_line.cpp:75
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
Definition: sch_line.cpp:682
PLOT_DASH_TYPE GetLineStyle() const
Definition: sch_line.cpp:246
VTBL_ENTRY PROJECT_FILE & GetProjectFile() const
Definition: project.h:143
const BITMAP_OPAQUE add_line_xpm[1]
Definition: add_line.cpp:30
double GetLength() const
Definition: sch_line.cpp:181
bool m_startIsDangling
True if start point is not connected.
Definition: sch_line.h:39
int GetPenWidth() const override
Definition: sch_line.cpp:275
PLOT_DASH_TYPE GetPlotStyle() const
Definition: sch_item.h:172
NET_SETTINGS stores various net-related settings in a project context.
Definition: net_settings.h:31
void SetLineColor(const COLOR4D &aColor)
Definition: sch_line.cpp:187
bool IsEndPoint(const wxPoint &aPoint) const
Definition: sch_line.h:87
#define STRUCT_DELETED
flag indication structures to be erased
Definition: eda_item.h:115
int GetWidth() const
Definition: sch_item.h:169
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
NETCLASS * GetDefaultPtr() const
Definition: netclass.h:271
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color, wxPenStyle aStyle)
Definition: gr_basic.cpp:228
bool doIsConnected(const wxPoint &aPosition) const override
Provide the object specific test to see if it is connected to aPosition.
Definition: sch_line.cpp:761
void GetSelectedPoints(std::vector< wxPoint > &aPoints) const
Definition: sch_line.cpp:635
#define DEFAULT_LINE_THICKNESS
The default wire width in mils. (can be changed in preference menu)
static PLOT_DASH_TYPE GetLineStyleByName(const wxString &aStyleName)
Definition: sch_line.cpp:93
wxPoint m_end
Line end point.
Definition: sch_line.h:42
void SwapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
Definition: sch_line.cpp:747
STROKE_PARAMS m_stroke
Line stroke properties.
Definition: sch_line.h:43
PLOT_DASH_TYPE
Dashed line types.
Definition: plotter.h:104
#define DEFAULT_BUS_THICKNESS
The default noconnect size in mils.
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:279
void MoveTo(const wxPoint &pos)
Definition: plotter.h:273
EDA_UNITS
Definition: eda_units.h:38
bool IsSameQuadrant(SCH_LINE *aLine, const wxPoint &aPosition)
Check if two lines are in the same quadrant as each other, using a reference point as the origin.
Definition: sch_line.cpp:367
#define STARTPOINT
When a line is selected, these flags indicate which.
Definition: eda_item.h:111
Base plotter engine class.
Definition: plotter.h:131
COLOR4D GetColor() const
Definition: sch_item.h:175
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:165
PLOT_DASH_TYPE GetEffectiveLineStyle() const
Definition: sch_line.cpp:255
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: sch_line.cpp:66
void MoveEnd(const wxPoint &aMoveVector)
Definition: sch_line.cpp:129
bool operator<(const SCH_ITEM &aItem) const override
Definition: sch_line.cpp:693
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
#define _(s)
Definition: 3d_actions.cpp:33
#define DEFAULT_WIRE_THICKNESS
The default bus width in mils. (can be changed in preference menu)
STATUS_FLAGS m_Flags
Definition: eda_item.h:165
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
PROJECT & Prj() const
Return a reference to the project this schematic is part of.
Definition: schematic.h:79
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: eda_item.h:148
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:103
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
Definition: eda_rect.cpp:150
const BITMAP_OPAQUE add_bus_xpm[1]
Definition: add_bus.cpp:30
void Print(RENDER_SETTINGS *aSettings, const wxPoint &aOffset) override
Print a schematic item.
Definition: sch_line.cpp:317
void MirrorY(int aYaxis_position) override
Mirror item relative to the Y axis about aYaxis_position.
Definition: sch_line.cpp:341
int GetDefaultPenWidth() const
void SetColor(const COLOR4D &aColor)
Definition: sch_item.h:176
#define ENDPOINT
ends. (Used to support dragging.)
Definition: eda_item.h:112
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemList, const SCH_SHEET_PATH *aPath=nullptr) override
Test the schematic item to aItemList to check if it's dangling state has changed.
Definition: sch_line.cpp:539
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Definition: sch_line.cpp:164
Helper class used to store the state of schematic items that can be connected to other schematic item...
Definition: sch_item.h:85
EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:54
#define SKIP_STRUCT
flag indicating that the structure should be ignored
Definition: eda_item.h:117
void SetPosition(const wxPoint &aPosition) override
Definition: sch_line.cpp:803
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:194
wxPoint m_start
Line start point.
Definition: sch_line.h:41
SCH_LINE(const wxPoint &pos=wxPoint(0, 0), int layer=LAYER_NOTES)
Definition: sch_line.cpp:36
wxPenStyle GetwxPenStyle(PLOT_DASH_TYPE aType)
Convert KiCad line plot styles to wxWidgets device context styles.
Definition: plotter.cpp:611
virtual void SetDash(PLOT_DASH_TYPE dashed)=0
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:363
std::vector< wxPoint > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Definition: sch_line.cpp:629
KICAD_T Type() const
Function Type()
Definition: eda_item.h:182
virtual void SetCurrentLineWidth(int width, void *aData=NULL)=0
Set the line width for the next drawing.
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:100
wxPoint GetEndPoint() const
Definition: sch_line.h:97