/** * In a contiguous list of wires, remove wires that backtrack over the previous * wire. Example: * * Wire is added: * ----------------------------------------> * * A second wire backtracks over it: * -------------------<====================> * * RemoveBacktracks is called: * -------------------> */ static void RemoveBacktracks( DLIST<SCH_ITEM>& aWires ) { SCH_LINE* last_line = NULL; EDA_ITEM* first = aWires.GetFirst(); for( EDA_ITEM* p = first; p; ) { SCH_LINE *line = dynamic_cast<SCH_LINE*>( p ); if( !line ) { wxFAIL_MSG( "RemoveBacktracks() requires SCH_LINE items" ); break; } p = line->Next(); if( last_line ) { wxASSERT_MSG( last_line->GetEndPoint() == line->GetStartPoint(), "RemoveBacktracks() requires contiguous lines" ); if( IsPointOnSegment( last_line->GetStartPoint(), line->GetStartPoint(), line->GetEndPoint() ) ) { last_line->SetEndPoint( line->GetEndPoint() ); delete s_wires.Remove( line ); } else last_line = line; } else last_line = line; } }
/** * In a contiguous list of wires, remove wires that backtrack over the previous * wire. Example: * * Wire is added: * ----------------------------------------> * * A second wire backtracks over it: * -------------------<====================> * * RemoveBacktracks is called: * -------------------> */ static void RemoveBacktracks( DLIST<SCH_ITEM>& aWires ) { EDA_ITEM* first = aWires.GetFirst(); std::vector<SCH_LINE*> last_lines; for( EDA_ITEM* p = first; p; ) { SCH_LINE *line = static_cast<SCH_LINE*>( p ); p = line->Next(); if( !last_lines.empty() ) { SCH_LINE* last_line = last_lines[last_lines.size() - 1]; bool contiguous = ( last_line->GetEndPoint() == line->GetStartPoint() ); bool backtracks = IsPointOnSegment( last_line->GetStartPoint(), last_line->GetEndPoint(), line->GetEndPoint() ); bool total_backtrack = ( last_line->GetStartPoint() == line->GetEndPoint() ); if( contiguous && backtracks ) { if( total_backtrack ) { delete s_wires.Remove( last_line ); delete s_wires.Remove( line ); last_lines.pop_back(); } else { last_line->SetEndPoint( line->GetEndPoint() ); delete s_wires.Remove( line ); } } else { last_lines.push_back( line ); } } else { last_lines.push_back( line ); } } }
void SCH_EDIT_FRAME::EndSegment( wxDC* DC ) { SCH_SCREEN* screen = GetScreen(); SCH_LINE* segment = (SCH_LINE*) screen->GetCurItem(); if( segment == NULL || segment->Type() != SCH_LINE_T || !segment->IsNew() ) return; // Delete zero length segments and clear item flags. SCH_ITEM* item = s_wires.begin(); while( item ) { item->ClearFlags(); wxCHECK_RET( item->Type() == SCH_LINE_T, wxT( "Unexpected object type in wire list." ) ); segment = (SCH_LINE*) item; item = item->Next(); if( segment->IsNull() ) delete s_wires.Remove( segment ); } if( s_wires.GetCount() == 0 ) return; // Get the last non-null wire (this is the last created segment). SetRepeatItem( segment = (SCH_LINE*) s_wires.GetLast() ); screen->SetCurItem( NULL ); m_canvas->EndMouseCapture( -1, -1, wxEmptyString, false ); // store the terminal point of this last segment: a junction could be needed // (the last wire could be merged/deleted/modified, and lost) wxPoint endpoint = segment->GetEndPoint(); // store the starting point of this first segment: a junction could be needed SCH_LINE* firstsegment = (SCH_LINE*) s_wires.GetFirst(); wxPoint startPoint = firstsegment->GetStartPoint(); // Save the old wires for the undo command DLIST< SCH_ITEM > oldWires; // stores here the old wires GetScreen()->ExtractWires( oldWires, true ); // Save them in oldWires list // Put the snap shot of the previous wire, buses, and junctions in the undo/redo list. PICKED_ITEMS_LIST oldItems; oldItems.m_Status = UR_WIRE_IMAGE; while( oldWires.GetCount() != 0 ) { ITEM_PICKER picker = ITEM_PICKER( oldWires.PopFront(), UR_WIRE_IMAGE ); oldItems.PushItem( picker ); } SaveCopyInUndoList( oldItems, UR_WIRE_IMAGE ); // Remove segments backtracking over others RemoveBacktracks( s_wires ); // Add the new wires screen->Append( s_wires ); // Correct and remove segments that need to be merged. screen->SchematicCleanUp(); // A junction could be needed to connect the end point of the last created segment. if( screen->IsJunctionNeeded( endpoint ) ) screen->Append( AddJunction( DC, endpoint ) ); // A junction could be needed to connect the start point of the set of new created wires if( screen->IsJunctionNeeded( startPoint ) ) screen->Append( AddJunction( DC, startPoint ) ); m_canvas->Refresh(); OnModify(); }