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.

210 lines
7.0 KiB

5 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
  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. #include <core/kicad_algo.h>
  25. #include <general.h>
  26. #include <sch_bus_entry.h>
  27. #include <sch_edit_frame.h>
  28. #include <sch_junction.h>
  29. #include <sch_line.h>
  30. #include <sch_no_connect.h>
  31. #include <sch_commit.h>
  32. #include <tool/tool_manager.h>
  33. #include <tools/sch_line_wire_bus_tool.h>
  34. #include <tools/sch_selection_tool.h>
  35. #include <trigo.h>
  36. void SCH_EDIT_FRAME::TestDanglingEnds()
  37. {
  38. std::function<void( SCH_ITEM* )> changeHandler =
  39. [&]( SCH_ITEM* aChangedItem ) -> void
  40. {
  41. GetCanvas()->GetView()->Update( aChangedItem, KIGFX::REPAINT );
  42. };
  43. GetScreen()->TestDanglingEnds( nullptr, &changeHandler );
  44. }
  45. bool SCH_EDIT_FRAME::TrimWire( SCH_COMMIT* aCommit, const VECTOR2I& aStart, const VECTOR2I& aEnd )
  46. {
  47. if( aStart == aEnd )
  48. return false;
  49. SCH_SCREEN* screen = GetScreen();
  50. std::vector<SCH_LINE*> wires;
  51. BOX2I bb( aStart );
  52. SCH_LINE_WIRE_BUS_TOOL* lwbTool = m_toolManager->GetTool<SCH_LINE_WIRE_BUS_TOOL>();
  53. bb.Merge( aEnd );
  54. // We cannot modify the RTree while iterating, so push the possible
  55. // wires into a separate structure.
  56. for( EDA_ITEM* item : screen->Items().Overlapping( bb ) )
  57. {
  58. SCH_LINE* line = static_cast<SCH_LINE*>( item );
  59. if( item->Type() == SCH_LINE_T && line->GetLayer() == LAYER_WIRE )
  60. wires.push_back( line );
  61. }
  62. for( SCH_LINE* line : wires )
  63. {
  64. // Don't remove wires that are already deleted or are currently being dragged
  65. if( line->GetEditFlags() & ( STRUCT_DELETED | IS_MOVING | SKIP_STRUCT ) )
  66. continue;
  67. if( !IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), aStart ) ||
  68. !IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), aEnd ) )
  69. {
  70. continue;
  71. }
  72. // Don't remove entire wires
  73. if( ( line->GetStartPoint() == aStart && line->GetEndPoint() == aEnd )
  74. || ( line->GetStartPoint() == aEnd && line->GetEndPoint() == aStart ) )
  75. {
  76. continue;
  77. }
  78. // Step 1: break the segment on one end.
  79. // Ensure that *line points to the segment containing aEnd
  80. SCH_LINE* new_line;
  81. lwbTool->BreakSegment( aCommit, line, aStart, &new_line, screen );
  82. if( IsPointOnSegment( new_line->GetStartPoint(), new_line->GetEndPoint(), aEnd ) )
  83. line = new_line;
  84. // Step 2: break the remaining segment.
  85. // Ensure that *line _also_ contains aStart. This is our overlapping segment
  86. lwbTool->BreakSegment( aCommit, line, aEnd, &new_line, screen );
  87. if( IsPointOnSegment( new_line->GetStartPoint(), new_line->GetEndPoint(), aStart ) )
  88. line = new_line;
  89. RemoveFromScreen( line, screen );
  90. aCommit->Removed( line, screen );
  91. return true;
  92. }
  93. return false;
  94. }
  95. void SCH_EDIT_FRAME::DeleteJunction( SCH_COMMIT* aCommit, SCH_ITEM* aJunction )
  96. {
  97. SCH_SCREEN* screen = GetScreen();
  98. PICKED_ITEMS_LIST undoList;
  99. SCH_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<SCH_SELECTION_TOOL>();
  100. aJunction->SetFlags( STRUCT_DELETED );
  101. RemoveFromScreen( aJunction, screen );
  102. aCommit->Removed( aJunction, screen );
  103. /// Note that std::list or similar is required here as we may insert values in the
  104. /// loop below. This will invalidate iterators in a std::vector or std::deque
  105. std::list<SCH_LINE*> lines;
  106. for( SCH_ITEM* item : screen->Items().Overlapping( SCH_LINE_T, aJunction->GetPosition() ) )
  107. {
  108. SCH_LINE* line = static_cast<SCH_LINE*>( item );
  109. if( ( line->IsWire() || line->IsBus() )
  110. && line->IsEndPoint( aJunction->GetPosition() )
  111. && !( line->GetEditFlags() & STRUCT_DELETED ) )
  112. {
  113. lines.push_back( line );
  114. }
  115. }
  116. alg::for_all_pairs( lines.begin(), lines.end(),
  117. [&]( SCH_LINE* firstLine, SCH_LINE* secondLine )
  118. {
  119. if( ( firstLine->GetEditFlags() & STRUCT_DELETED )
  120. || ( secondLine->GetEditFlags() & STRUCT_DELETED )
  121. || !secondLine->IsParallel( firstLine ) )
  122. {
  123. return;
  124. }
  125. // Remove identical lines
  126. if( firstLine->IsEndPoint( secondLine->GetStartPoint() )
  127. && firstLine->IsEndPoint( secondLine->GetEndPoint() ) )
  128. {
  129. firstLine->SetFlags( STRUCT_DELETED );
  130. return;
  131. }
  132. // Try to merge the remaining lines
  133. if( SCH_LINE* new_line = secondLine->MergeOverlap( screen, firstLine, false ) )
  134. {
  135. firstLine->SetFlags( STRUCT_DELETED );
  136. secondLine->SetFlags( STRUCT_DELETED );
  137. AddToScreen( new_line, screen );
  138. aCommit->Added( new_line, screen );
  139. if( new_line->IsSelected() )
  140. selectionTool->AddItemToSel( new_line, true /*quiet mode*/ );
  141. lines.push_back( new_line );
  142. }
  143. } );
  144. for( SCH_LINE* line : lines )
  145. {
  146. if( line->GetEditFlags() & STRUCT_DELETED )
  147. {
  148. if( line->IsSelected() )
  149. selectionTool->RemoveItemFromSel( line, true /*quiet mode*/ );
  150. RemoveFromScreen( line, screen );
  151. aCommit->Removed( line, screen );
  152. }
  153. }
  154. }
  155. void SCH_EDIT_FRAME::UpdateHopOveredWires( SCH_ITEM* aItem )
  156. {
  157. std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> items;
  158. GetCanvas()->GetView()->Query( aItem->GetBoundingBox(), items );
  159. for( const auto& it : items )
  160. {
  161. if( !it.first->IsSCH_ITEM() )
  162. continue;
  163. SCH_ITEM* item = static_cast<SCH_ITEM*>( it.first );
  164. if( item == aItem )
  165. continue;
  166. if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T } ) )
  167. {
  168. GetCanvas()->GetView()->Update( item );
  169. }
  170. }
  171. }