You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
4.4 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software: you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation, either version 3 of the License, or (at your
  9. * option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "junction_helpers.h"
  20. #include <sch_line.h>
  21. using namespace JUNCTION_HELPERS;
  22. POINT_INFO JUNCTION_HELPERS::AnalyzePoint( const EE_RTREE& aItems, const VECTOR2I& aPosition,
  23. bool aBreakCrossings )
  24. {
  25. enum layers
  26. {
  27. WIRES = 0,
  28. BUSES
  29. };
  30. POINT_INFO info{};
  31. info.hasBusEntry = false;
  32. info.hasExplicitJunctionDot = false;
  33. info.isJunction = false;
  34. info.hasBusEntryToMultipleWires = false;
  35. bool breakLines[2] = { false };
  36. std::unordered_set<int> exitAngles[2];
  37. std::vector<const SCH_LINE*> midPointLines[2];
  38. // A pin at 90° still shouldn't match a line at 90° so just give pins unique numbers
  39. int uniqueAngle = 10000;
  40. for( const SCH_ITEM* item : aItems.Overlapping( aPosition ) )
  41. {
  42. if( item->GetEditFlags() & STRUCT_DELETED )
  43. continue;
  44. switch( item->Type() )
  45. {
  46. case SCH_JUNCTION_T:
  47. if( item->HitTest( aPosition, -1 ) )
  48. info.hasExplicitJunctionDot = true;
  49. break;
  50. case SCH_LINE_T:
  51. {
  52. const SCH_LINE* line = static_cast<const SCH_LINE*>( item );
  53. int layer;
  54. if( line->GetStartPoint() == line->GetEndPoint() )
  55. break;
  56. else if( line->GetLayer() == LAYER_WIRE )
  57. layer = WIRES;
  58. else if( line->GetLayer() == LAYER_BUS )
  59. layer = BUSES;
  60. else
  61. break;
  62. if( line->IsConnected( aPosition ) )
  63. {
  64. breakLines[layer] = true;
  65. exitAngles[layer].insert( line->GetAngleFrom( aPosition ) );
  66. }
  67. else if( line->HitTest( aPosition, -1 ) )
  68. {
  69. if( aBreakCrossings )
  70. breakLines[layer] = true;
  71. // Defer any line midpoints until we know whether or not we're breaking them
  72. midPointLines[layer].push_back( line );
  73. }
  74. }
  75. break;
  76. case SCH_BUS_WIRE_ENTRY_T:
  77. if( item->IsConnected( aPosition ) )
  78. {
  79. breakLines[BUSES] = true;
  80. exitAngles[BUSES].insert( uniqueAngle++ );
  81. breakLines[WIRES] = true;
  82. exitAngles[WIRES].insert( uniqueAngle++ );
  83. info.hasBusEntry = true;
  84. }
  85. break;
  86. case SCH_SYMBOL_T:
  87. case SCH_SHEET_T:
  88. if( item->IsConnected( aPosition ) )
  89. {
  90. breakLines[WIRES] = true;
  91. exitAngles[WIRES].insert( uniqueAngle++ );
  92. }
  93. break;
  94. default: break;
  95. }
  96. }
  97. for( int layer : { WIRES, BUSES } )
  98. {
  99. if( breakLines[layer] )
  100. {
  101. for( const SCH_LINE* line : midPointLines[layer] )
  102. {
  103. exitAngles[layer].insert( line->GetAngleFrom( aPosition ) );
  104. exitAngles[layer].insert( line->GetReverseAngleFrom( aPosition ) );
  105. }
  106. }
  107. }
  108. if( info.hasBusEntry )
  109. {
  110. // The bus entry and one wire is 2 wires, and the one entry is exactly one bus
  111. // Any more wires must be multiple wires, but any more buses means a wire
  112. // crossing at the bus entry root.
  113. info.hasBusEntryToMultipleWires =
  114. exitAngles[WIRES].size() > 2 && exitAngles[BUSES].size() == 1;
  115. }
  116. // Any three things of the same type is a junction of some sort
  117. info.isJunction = exitAngles[WIRES].size() >= 3 || exitAngles[BUSES].size() >= 3;
  118. return info;
  119. }