kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #32013
Re: [PATCH] Eeschema automatic manage junctions
Hi Orson-
Thanks for the pointer. I found and corrected the issue and updated the
commit messages to remove the NEW/CHANGED tags that didn't reflect
user-visible changes.
Since we're now in feature freeze, this may be too late for 5.0. However,
this does address a number of bug reports so I'm attaching the minimized
patchset in case Wayne would like to merge it. If Wayne decides that this
more feature/less bugfix, I'll hold onto the patchset until we have a 6-dev
branch.
Best-
Seth
On Sat, Nov 25, 2017 at 7:37 AM, Maciej Suminski <maciej.suminski@xxxxxxx>
wrote:
> Hi Seth,
>
> I tried this with interf_u demo shipped with the source code. There are
> four capacitors in the left bottom corner - try dragging one of the
> middle ones out. If you cannot reproduce the problem, I will try to
> shoot a video.
>
> Cheers,
> Orson
>
> On 11/25/2017 03:58 PM, Seth Hillbrand wrote:
> > Hi Orson-
> >
> > Thanks for the test and the clarification of the documentation.
> >
> > On the schematic, I can't seem to recreate the issue you document in the
> > image. Is the example schematic one you can share?
> >
> > Best-
> > Seth
> >
> > On Fri, Nov 24, 2017 at 6:50 AM, Maciej Sumiński <
> maciej.suminski@xxxxxxx>
> > wrote:
> >
> >> Hi Seth,
> >>
> >> I tested the branch and I consider it a significant improvement to the
> >> way junctions are handled. I confirm it fixes the four bugs mentioned in
> >> patch 0011, apart from a single case when a parallel component is
> >> dragged out. In this case junctions are not still not auto deleted (see
> >> [1], the rightmost picture "Junction is not auto deleted"), but at least
> >> the overlapping wires are merged. It is not a big deal IMHO, especially
> >> the patch set fixes a lot of other issues.
> >>
> >> It has not been stated explicitly, but I thought we will use
> >> NEW/REMOVE/CHANGE tags for listing changes that are perceived by the
> >> user. Therefore:
> >>
> >> CHANGE: DeleteItem removes junctions that are no longer needed.
> >>
> >> informs the user about an improvement, but:
> >>
> >> CHANGE: DeleteItemsInList shares the code for DeleteItem.
> >>
> >> seems to be too detailed and does not need to be reflected in the user
> >> documentation.
> >>
> >> What do you think? I will try to come up with a short paragraph that can
> >> be added to the website to make things clear.
> >>
> >> Regards,
> >> Orson
> >>
> >> 1.
> >> https://launchpadlibrarian.net/213748651/KICAD%20-%20BUG%
> >> 20REPORT%20-%20EESCHEMA%20-%20SOME%20DRAG%20ISSUES.jpg
> >>
> >> On 11/22/2017 09:07 PM, Seth Hillbrand wrote:
> >>> Updated patchset for this proposal, rebased to master. I've also
> updated
> >>> the commit messages to match the CHANGE:/NEW: format and added one new
> >> bug
> >>> from launchpad that this addresses.
> >>>
> >>> -Seth
> >>>
> >>> On Wed, Nov 8, 2017 at 3:59 AM, Nick Østergaard <oe.nick@xxxxxxxxx>
> >> wrote:
> >>>
> >>>> For that specific issue with the junction drawing, there is a patch in
> >> the
> >>>> thread "[Kicad-developers] [PATCH] Draw junctions last"
> >>>>
> >>>> 2017-11-03 13:12 GMT+01:00 Jon Evans <jon@xxxxxxxxxxxxx>:
> >>>>
> >>>>> I looked at fixing this and some other related things, and decided to
> >>>>> just wait for the GAL port. There will need to be huge refactoring of
> >> the
> >>>>> eeschema draw code as part of that effort, so putting much effort
> into
> >>>>> making the wxDC drawing better seems not worth it.
> >>>>>
> >>>>> -Jon
> >>>>>
> >>>>> On Nov 3, 2017 00:08, "Kevin Cozens" <kevin@xxxxxxxxx> wrote:
> >>>>>
> >>>>> On 2017-11-02 06:31 PM, Seth Hillbrand wrote:
> >>>>>
> >>>>>> Please let me know if there are any additional issues or suggestions
> >> for
> >>>>>> improvement.
> >>>>>>
> >>>>>
> >>>>> How difficult would it be to have junctions draw last on schematics?
> >>>>> There is a minor negative visual effect when you have a component
> with
> >> one
> >>>>> end joined to a wire by a junction and you replace the component.
> >>>>>
> >>>>> When you replace the component the pin of the component is now seen
> >>>>> extending through the round disc of the junction to the center of the
> >>>>> junction. I prefer to always see just the full round disc of a
> junction
> >>>>> mark even if I have replaced a component since placing the junction.
> >>>>>
> >>>>> --
> >>>>> Cheers!
> >>>>>
> >>>>> Kevin.
> >>>>>
> >>>>> http://www.ve3syb.ca/ |"Nerds make the shiny things that
> >>>>> distract
> >>>>> Owner of Elecraft K2 #2172 | the mouth-breathers, and that's why
> >>>>> we're
> >>>>> | powerful!"
> >>>>> #include <disclaimer/favourite> | --Chris Hardwick
> >>>>>
> >>>>>
> >>>>> _______________________________________________
> >>>>> Mailing list: https://launchpad.net/~kicad-developers
> >>>>> Post to : kicad-developers@xxxxxxxxxxxxxxxxxxx
> >>>>> Unsubscribe : https://launchpad.net/~kicad-developers
> >>>>> More help : https://help.launchpad.net/ListHelp
> >>>>>
> >>>>>
> >>>>>
> >>>>> _______________________________________________
> >>>>> Mailing list: https://launchpad.net/~kicad-developers
> >>>>> Post to : kicad-developers@xxxxxxxxxxxxxxxxxxx
> >>>>> Unsubscribe : https://launchpad.net/~kicad-developers
> >>>>> More help : https://help.launchpad.net/ListHelp
> >>>>>
> >>>>>
> >>>>
> >>>> _______________________________________________
> >>>> Mailing list: https://launchpad.net/~kicad-developers
> >>>> Post to : kicad-developers@xxxxxxxxxxxxxxxxxxx
> >>>> Unsubscribe : https://launchpad.net/~kicad-developers
> >>>> More help : https://help.launchpad.net/ListHelp
> >>>>
> >>>>
> >>>
> >>>
> >>>
> >>> _______________________________________________
> >>> Mailing list: https://launchpad.net/~kicad-developers
> >>> Post to : kicad-developers@xxxxxxxxxxxxxxxxxxx
> >>> Unsubscribe : https://launchpad.net/~kicad-developers
> >>> More help : https://help.launchpad.net/ListHelp
> >>>
> >>
> >>
> >>
> >>
> >> _______________________________________________
> >> Mailing list: https://launchpad.net/~kicad-developers
> >> Post to : kicad-developers@xxxxxxxxxxxxxxxxxxx
> >> Unsubscribe : https://launchpad.net/~kicad-developers
> >> More help : https://help.launchpad.net/ListHelp
> >>
> >>
> >
>
From 9348910fe118106d845f5aeff0e857c3a4f4afec Mon Sep 17 00:00:00 2001
From: Seth Hillbrand <hillbrand@xxxxxxxxxxx>
Date: Mon, 27 Nov 2017 11:27:24 -0800
Subject: [PATCH 9/9] Eeschema: Automatically manage junctions
CHANGE: eeschema automatically adds and removes junctions
when required by the schematic
Fixes: lp:593888
* https://bugs.launchpad.net/kicad/+bug/593888
Fixes: lp:1482111
* https://bugs.launchpad.net/kicad/+bug/1482111
Fixes: lp:1563153
* https://bugs.launchpad.net/kicad/+bug/1563153
Fixes: lp:1730219
* https://bugs.launchpad.net/kicad/+bug/1730219
Fixes: lp:1491052
* https://bugs.launchpad.net/kicad/+bug/1491052
---
eeschema/block.cpp | 15 ++-
eeschema/bus-wire-junction.cpp | 223 +++++++++++++++++++--------------
eeschema/class_sch_screen.h | 14 +--
eeschema/files-io.cpp | 10 ++
eeschema/hierarch.cpp | 8 +-
eeschema/operations_on_items_lists.cpp | 40 ++++++
eeschema/project_rescue.cpp | 1 +
eeschema/sch_line.cpp | 21 ++--
eeschema/sch_line.h | 6 +-
eeschema/sch_screen.cpp | 82 +++++++-----
eeschema/schedit.cpp | 3 +
eeschema/schframe.cpp | 9 ++
eeschema/schframe.h | 25 +++-
13 files changed, 298 insertions(+), 159 deletions(-)
diff --git a/eeschema/block.cpp b/eeschema/block.cpp
index f4aa8517c..b092d523d 100644
--- a/eeschema/block.cpp
+++ b/eeschema/block.cpp
@@ -127,9 +127,8 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
if( m_canvas->IsMouseCaptured() )
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
- SaveCopyInUndoList( block->GetItems(), UR_MOVED, false, block->GetMoveVector() );
+ SaveCopyInUndoList( block->GetItems(), UR_CHANGED, false, block->GetMoveVector() );
MoveItemsInList( block->GetItems(), block->GetMoveVector() );
- block->ClearItemsList();
break;
case BLOCK_DUPLICATE: /* Duplicate */
@@ -141,8 +140,6 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
SaveCopyInUndoList( block->GetItems(),
( block->GetCommand() == BLOCK_PRESELECT_MOVE ) ? UR_CHANGED : UR_NEW );
-
- block->ClearItemsList();
break;
case BLOCK_PASTE:
@@ -150,13 +147,15 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
PasteListOfItems( DC );
- block->ClearItemsList();
break;
default: // others are handled by HandleBlockEnd()
break;
}
+ CheckJunctionsInList( block->GetItems(), true );
+ block->ClearItemsList();
+ SchematicCleanUp( true );
OnModify();
// clear dome flags and pointers
@@ -218,6 +217,8 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
SetCrossHairPosition( rotationPoint );
SaveCopyInUndoList( block->GetItems(), UR_ROTATED, false, rotationPoint );
RotateListOfItems( block->GetItems(), rotationPoint );
+ CheckJunctionsInList( block->GetItems(), true );
+ SchematicCleanUp( true );
OnModify();
}
@@ -270,6 +271,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
if( block->GetCount() )
{
DeleteItemsInList( block->GetItems() );
+ SchematicCleanUp( true );
OnModify();
}
block->ClearItemsList();
@@ -301,6 +303,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
copyBlockItems( block->GetItems() );
MoveItemsInList( m_blockItems.GetItems(), move_vector );
DeleteItemsInList( block->GetItems() );
+ SchematicCleanUp( true );
OnModify();
}
@@ -329,6 +332,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
SetCrossHairPosition( mirrorPoint );
SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_X, false, mirrorPoint );
MirrorX( block->GetItems(), mirrorPoint );
+ SchematicCleanUp( true );
OnModify();
}
@@ -348,6 +352,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
SetCrossHairPosition( mirrorPoint );
SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_Y, false, mirrorPoint );
MirrorY( block->GetItems(), mirrorPoint );
+ SchematicCleanUp( true );
OnModify();
}
diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp
index f3e2f2171..1cfce517e 100644
--- a/eeschema/bus-wire-junction.cpp
+++ b/eeschema/bus-wire-junction.cpp
@@ -266,82 +266,76 @@ void SCH_EDIT_FRAME::BeginSegment( wxDC* DC, int type )
}
}
+void SCH_EDIT_FRAME::GetSchematicConnections( std::vector< wxPoint >& aConnections )
+{
+ for( SCH_ITEM* item = GetScreen()->GetDrawItems(); item; item = item->Next() )
+ item->GetConnectionPoints( aConnections );
+
+ // We always have some overlapping connection points. Drop duplicates here
+ std::sort( aConnections.begin(), aConnections.end(),
+ []( wxPoint& a, wxPoint& b ) -> bool
+ { return a.x < b.x || (a.x == b.x && a.y < b.y); } );
+ aConnections.erase( unique( aConnections.begin(), aConnections.end() ), aConnections.end() );
+}
void SCH_EDIT_FRAME::EndSegment()
{
SCH_SCREEN* screen = GetScreen();
SCH_LINE* segment = (SCH_LINE*) screen->GetCurItem();
+ PICKED_ITEMS_LIST itemList;
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 );
- }
+ // Remove segments backtracking over others
+ RemoveBacktracks( s_wires );
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();
+ // Collect the possible connection points for the new lines
+ std::vector< wxPoint > connections;
+ std::vector< wxPoint > new_ends;
- // 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();
+ GetSchematicConnections( connections );
+ // Check each new segment for possible junctions and add/split if needed
+ for( SCH_ITEM* wire = s_wires.GetFirst(); wire; wire=wire->Next() )
+ {
+ SCH_LINE* test_line = (SCH_LINE*) wire;
+ if( wire->GetFlags() & SKIP_STRUCT )
+ continue;
- // 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;
+ wire->GetConnectionPoints( new_ends );
- while( oldWires.GetCount() != 0 )
- {
- ITEM_PICKER picker = ITEM_PICKER( oldWires.PopFront(), UR_WIRE_IMAGE );
- oldItems.PushItem( picker );
+ for( auto i : connections )
+ {
+ if( IsPointOnSegment( test_line->GetStartPoint(), test_line->GetEndPoint(), i ) )
+ {
+ new_ends.push_back( i );
+ }
+ }
+ itemList.PushItem( ITEM_PICKER( wire, UR_NEW ) );
}
- SaveCopyInUndoList( oldItems, UR_WIRE_IMAGE );
-
- // Remove segments backtracking over others
- RemoveBacktracks( s_wires );
+ // Get the last non-null wire (this is the last created segment).
+ SetRepeatItem( segment = (SCH_LINE*) s_wires.GetLast() );
// Add the new wires
screen->Append( s_wires );
+ SaveCopyInUndoList(itemList, UR_NEW);
// Correct and remove segments that need to be merged.
- SchematicCleanUp();
-
- // A junction could be needed to connect the end point of the last created segment.
- if( screen->IsJunctionNeeded( endpoint ) )
- screen->Append( AddJunction( 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( startPoint ) );
-
- m_canvas->Refresh();
+ SchematicCleanUp( true );
+ for( auto i : new_ends )
+ {
+ if( screen->IsJunctionNeeded( i, true ) )
+ AddJunction( i, true );
+ }
+ screen->TestDanglingEnds();
+ screen->ClearDrawingState();
+ screen->SetCurItem( NULL );
+ m_canvas->EndMouseCapture( -1, -1, wxEmptyString, false );
OnModify();
}
@@ -441,54 +435,100 @@ void SCH_EDIT_FRAME::SaveWireImage()
}
-bool SCH_EDIT_FRAME::SchematicCleanUp()
+bool SCH_EDIT_FRAME::SchematicCleanUp( bool aAppend )
{
- bool modified = false;
+ SCH_ITEM* item = NULL;
+ SCH_ITEM* secondItem = NULL;
+ PICKED_ITEMS_LIST itemList;
+ SCH_SCREEN* screen = GetScreen();
- for( SCH_ITEM* item = GetScreen()->GetDrawItems() ; item; item = item->Next() )
+ auto remove_item = [ &itemList, screen ]( SCH_ITEM* aItem ) -> void
{
- if( ( item->Type() != SCH_LINE_T ) && ( item->Type() != SCH_JUNCTION_T ) )
+ aItem->SetFlags( STRUCT_DELETED );
+ itemList.PushItem( ITEM_PICKER( aItem, UR_DELETED ) );
+ };
+
+ BreakSegmentsOnJunctions( true );
+
+ for( item = screen->GetDrawItems(); item; item = item->Next() )
+ {
+ if( ( item->Type() != SCH_LINE_T ) &&
+ ( item->Type() != SCH_JUNCTION_T ) &&
+ ( item->Type() != SCH_NO_CONNECT_T ))
continue;
- bool restart;
+ if( item->GetFlags() & STRUCT_DELETED )
+ continue;
- for( SCH_ITEM* testItem = item->Next(); testItem; testItem = restart ? GetScreen()->GetDrawItems() : testItem->Next() )
+ // Remove unneeded junctions
+ if( ( item->Type() == SCH_JUNCTION_T )
+ && ( !screen->IsJunctionNeeded( item->GetPosition() ) ) )
{
- restart = false;
+ remove_item( item );
+ continue;
+ }
+ // Remove zero-length lines
+ if( item->Type() == SCH_LINE_T
+ && ( (SCH_LINE*) item )->IsNull() )
+ {
+ remove_item( item );
+ continue;
+ }
- if( ( item->Type() == SCH_LINE_T ) && ( testItem->Type() == SCH_LINE_T ) )
- {
- SCH_LINE* line = (SCH_LINE*) item;
+ for( secondItem = item->Next(); secondItem; secondItem = secondItem->Next() )
+ {
+ if( item->Type() != secondItem->Type() || ( secondItem->GetFlags() & STRUCT_DELETED ) )
+ continue;
- if( line->MergeOverlap( (SCH_LINE*) testItem ) )
- {
- // Keep the current flags, because the deleted segment can be flagged.
- item->SetFlags( testItem->GetFlags() );
- DeleteItem( testItem );
- restart = true;
- modified = true;
- }
- }
- else if ( ( ( item->Type() == SCH_JUNCTION_T )
- && ( testItem->Type() == SCH_JUNCTION_T ) ) && ( testItem != item ) )
+ // Merge overlapping lines
+ if( item->Type() == SCH_LINE_T )
{
- if ( testItem->HitTest( item->GetPosition() ) )
+ SCH_LINE* firstLine = (SCH_LINE*) item;
+ SCH_LINE* secondLine = (SCH_LINE*) secondItem;
+ SCH_LINE* line = NULL;
+ bool needed = false;
+
+ if( !secondLine->IsParallel( firstLine ) )
+ continue;
+
+ // Check if a junction needs to be kept
+ // This can only happen if:
+ // 1) the endpoints overlap,
+ // 2) the lines are not pointing in the same direction AND
+ // 3) IsJunction Needed is false
+ if( secondLine->IsEndPoint( firstLine->GetStartPoint() )
+ && !secondLine->IsSameQuadrant( firstLine, firstLine->GetStartPoint() ) )
+ needed = screen->IsJunctionNeeded( firstLine->GetStartPoint() );
+ else if( secondLine->IsEndPoint( firstLine->GetEndPoint() )
+ && !secondLine->IsSameQuadrant( firstLine, firstLine->GetEndPoint() ) )
+ needed = screen->IsJunctionNeeded( firstLine->GetEndPoint() );
+
+ if( !needed && ( line = (SCH_LINE*) secondLine->MergeOverlap( firstLine ) ) )
{
- // Keep the current flags, because the deleted segment can be flagged.
- item->SetFlags( testItem->GetFlags() );
- DeleteItem( testItem );
- restart = true;
- modified = true;
+ remove_item( item );
+ remove_item( secondItem );
+ itemList.PushItem( ITEM_PICKER( line, UR_NEW ) );
+ screen->Append( (SCH_ITEM*) line );
+ break;
}
}
+ // Remove duplicate junctions and no-connects
+ else if( secondItem->GetPosition() == item->GetPosition() )
+ remove_item( secondItem );
}
}
+ for( item = screen->GetDrawItems(); item; item = secondItem )
+ {
+ secondItem = item->Next();
+ if( item->GetFlags() & STRUCT_DELETED )
+ screen->Remove( item );
+ }
+ SaveCopyInUndoList( itemList, UR_CHANGED, aAppend );
- GetScreen()->TestDanglingEnds();
-
- return modified;
+ return !!( itemList.GetCount() );
}
+
bool SCH_EDIT_FRAME::BreakSegment( SCH_LINE *aSegment, const wxPoint& aPoint, bool aAppend )
{
if( !IsPointOnSegment( aSegment->GetStartPoint(), aSegment->GetEndPoint(), aPoint )
@@ -552,20 +592,17 @@ bool SCH_EDIT_FRAME::BreakSegmentsOnJunctions( bool aAppend )
}
-SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( const wxPoint& aPosition,
- bool aPutInUndoList )
+SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( const wxPoint& aPosition, bool aAppend )
{
SCH_JUNCTION* junction = new SCH_JUNCTION( aPosition );
+ SCH_SCREEN* screen = GetScreen();
+ bool broken_segments = false;
- SetRepeatItem( junction );
-
- if( aPutInUndoList )
- {
- GetScreen()->Append( junction );
- SaveCopyInUndoList( junction, UR_NEW );
- OnModify();
- }
-
+ screen->Append( junction );
+ broken_segments = BreakSegments( aPosition, aAppend );
+ screen->TestDanglingEnds();
+ OnModify();
+ SaveCopyInUndoList( junction, UR_NEW, broken_segments || aAppend );
return junction;
}
diff --git a/eeschema/class_sch_screen.h b/eeschema/class_sch_screen.h
index dd11205e0..a90763f35 100644
--- a/eeschema/class_sch_screen.h
+++ b/eeschema/class_sch_screen.h
@@ -336,19 +336,19 @@ public:
/**
* Test if a junction is required for the items at \a aPosition on the screen.
* <p>
- * A junction is required at \a aPosition if the following criteria are satisfied:
+ * A junction is required at \a aPosition if one of the following criteria is satisfied:
* <ul>
- * <li>one wire midpoint, one or more wire endpoints and no junction.</li>
- * <li>three or more wire endpoints and no junction.</li>
- * <li>two wire midpoints and no junction</li>
- * <li>one wire midpoint, a component pin, and no junction.</li>
- * <li>three wire endpoints, a component pin, and no junction.</li>
+ * <li>one wire midpoint and one or more wire endpoints;</li>
+ * <li>three or more wire endpoints;</li>
+ * <li>one wire midpoint and a component pin;</li>
+ * <li>two or more wire endpoints and a component pin.</li>
* </ul>
* </p>
* @param aPosition The position to test.
+ * @param aNew Checks if a _new_ junction is needed, i.e. there isn't one already
* @return True if a junction is required at \a aPosition.
*/
- bool IsJunctionNeeded( const wxPoint& aPosition );
+ bool IsJunctionNeeded( const wxPoint& aPosition, bool aNew = false );
/**
* Test if \a aPosition is a connection point on \a aLayer.
diff --git a/eeschema/files-io.cpp b/eeschema/files-io.cpp
index 931210b2c..94b0daeee 100644
--- a/eeschema/files-io.cpp
+++ b/eeschema/files-io.cpp
@@ -356,6 +356,11 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
}
schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
+
+ // Ensure the schematic is fully segmented on first display
+ BreakSegmentsOnJunctions();
+ SchematicCleanUp( true );
+ GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
GetScreen()->TestDanglingEnds(); // Only perform the dangling end test on root sheet.
}
@@ -768,6 +773,11 @@ bool SCH_EDIT_FRAME::ImportFile( const wxString& aFileName, int aFileType )
UpdateFileHistory( fullFileName );
schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
+
+ // Ensure the schematic is fully segmented on first display
+ BreakSegmentsOnJunctions();
+ SchematicCleanUp( true );
+ GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
GetScreen()->TestDanglingEnds(); // Only perform the dangling end test on root sheet.
GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
diff --git a/eeschema/hierarch.cpp b/eeschema/hierarch.cpp
index c41c82164..c65f388c4 100644
--- a/eeschema/hierarch.cpp
+++ b/eeschema/hierarch.cpp
@@ -299,7 +299,13 @@ void SCH_EDIT_FRAME::DisplayCurrentSheet()
screen->m_FirstRedraw = false;
SetCrossHairPosition( GetScrollCenterPosition() );
m_canvas->MoveCursorToCrossHair();
- SchematicCleanUp();
+
+ // Ensure the schematic is fully segmented on first display
+ BreakSegmentsOnJunctions();
+ SchematicCleanUp( true );
+ screen->ClearUndoORRedoList( screen->m_UndoList, 1 );
+
+ screen->TestDanglingEnds();
}
else
{
diff --git a/eeschema/operations_on_items_lists.cpp b/eeschema/operations_on_items_lists.cpp
index ad8313d38..d3ff28636 100644
--- a/eeschema/operations_on_items_lists.cpp
+++ b/eeschema/operations_on_items_lists.cpp
@@ -115,6 +115,46 @@ void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMoveVector
}
+void SCH_EDIT_FRAME::CheckJunctionsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend )
+{
+ std::vector< wxPoint > pts;
+ std::vector< wxPoint > connections;
+
+ GetSchematicConnections( connections );
+ for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
+ {
+ SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
+ item->GetConnectionPoints( pts );
+ if( item->Type() == SCH_LINE_T )
+ {
+ SCH_LINE* line = (SCH_LINE*) item;
+ for( auto i : connections )
+ if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), i ) )
+ pts.push_back( i );
+ }
+
+ }
+ // We always have some overlapping connection points. Drop duplicates here
+ std::sort( pts.begin(), pts.end(),
+ []( wxPoint& a, wxPoint& b ) -> bool
+ { return a.x < b.x || (a.x == b.x && a.y < b.y); } );
+ pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
+
+ for( auto point : pts )
+ {
+ if( GetScreen()->IsJunctionNeeded( point, true ) )
+ {
+ AddJunction( point, aAppend );
+ aAppend = true;
+ }
+ }
+}
+
+/**
+ * Function DeleteItemsInList
+ * delete schematic items in aItemsList
+ * deleted items are put in undo list
+ */
void SCH_EDIT_FRAME::DeleteItemsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend )
{
PICKED_ITEMS_LIST itemsList;
diff --git a/eeschema/project_rescue.cpp b/eeschema/project_rescue.cpp
index 0af8db517..61a096ac0 100644
--- a/eeschema/project_rescue.cpp
+++ b/eeschema/project_rescue.cpp
@@ -557,6 +557,7 @@ bool SCH_EDIT_FRAME::rescueProject( RESCUER& aRescuer, bool aRunningOnDemand )
// Clean up wire ends
SchematicCleanUp();
+ GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
m_canvas->Refresh( true );
OnModify();
diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp
index 7a05fee98..385858dad 100644
--- a/eeschema/sch_line.cpp
+++ b/eeschema/sch_line.cpp
@@ -388,7 +388,8 @@ bool SCH_LINE::IsParallel( SCH_LINE* aLine )
return !( (long long) firstSeg.x * secondSeg.y - (long long) firstSeg.y * secondSeg.x );
}
-bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
+
+EDA_ITEM* SCH_LINE::MergeOverlap( SCH_LINE* aLine )
{
auto less = []( const wxPoint& lhs, const wxPoint& rhs ) -> bool
{
@@ -396,12 +397,11 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
return lhs.y < rhs.y;
return lhs.x < rhs.x;
};
-
- wxCHECK_MSG( aLine != NULL && aLine->Type() == SCH_LINE_T, false,
+ wxCHECK_MSG( aLine != NULL && aLine->Type() == SCH_LINE_T, NULL,
wxT( "Cannot test line segment for overlap." ) );
if( this == aLine || GetLayer() != aLine->GetLayer() )
- return false;
+ return NULL;
SCH_LINE leftmost = SCH_LINE( *aLine );
SCH_LINE rightmost = SCH_LINE( *this );
@@ -428,16 +428,14 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
// If we end one before the beginning of the other, no overlap is possible
if( less( leftmost.m_end, other.m_start ) )
{
- return false;
+ return NULL;
}
// Search for a common end:
if( ( leftmost.m_start == other.m_start )
&& ( leftmost.m_end == other.m_end ) ) // Trivial case
{
- m_start = leftmost.m_start;
- m_end = leftmost.m_end;
- return true;
+ return new SCH_LINE( leftmost );
}
bool colinear = false;
@@ -471,12 +469,11 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
// Make a new segment that merges the 2 segments
if( colinear )
{
- m_start = leftmost.m_start;
- m_end = rightmost.m_end;
- return true;
+ leftmost.m_end = rightmost.m_end;
+ return new SCH_LINE( leftmost );
}
- return false;
+ return NULL;
}
diff --git a/eeschema/sch_line.h b/eeschema/sch_line.h
index 6b7594c31..e82d48268 100644
--- a/eeschema/sch_line.h
+++ b/eeschema/sch_line.h
@@ -133,14 +133,14 @@ public:
/**
* Check line against \a aLine to see if it overlaps and merge if it does.
*
- * This method will change the line to be equivalent of the line and \a aLine if the
+ * This method will return an equivalent of the union of line and \a aLine if the
* two lines overlap. This method is used to merge multiple line segments into a single
* line.
*
* @param aLine - Line to compare.
- * @return True if lines overlap and the line was merged with \a aLine.
+ * @return New line that combines the two or NULL on non-overlapping segments.
*/
- bool MergeOverlap( SCH_LINE* aLine );
+ EDA_ITEM* MergeOverlap( SCH_LINE* aLine );
/**
* Check if two lines are in the same quadrant as each other, using a reference point as
diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp
index c263787d7..a58cd11c9 100644
--- a/eeschema/sch_screen.cpp
+++ b/eeschema/sch_screen.cpp
@@ -55,6 +55,7 @@
#include <lib_pin.h>
#include <symbol_lib_table.h>
+#include <boost/foreach.hpp>
#define EESCHEMA_FILE_STAMP "EESchema"
@@ -346,20 +347,59 @@ void SCH_SCREEN::MarkConnections( SCH_LINE* aSegment )
}
-bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition )
+bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
{
- if( GetItem( aPosition, 0, SCH_JUNCTION_T ) )
- return false;
+ bool has_line = false;
+ bool has_nonparallel = false;
+ int end_count = 0;
+
+ std::vector< SCH_LINE* > lines;
- if( GetWire( aPosition, 0, EXCLUDE_END_POINTS_T ) )
+ for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
{
- if( GetWire( aPosition, 0, END_POINTS_ONLY_T ) )
- return true;
+ if( item->GetFlags() & STRUCT_DELETED )
+ continue;
+ if( aNew && ( item->Type() == SCH_JUNCTION_T ) && ( item->HitTest( aPosition ) ) )
+ return false;
- if( GetPin( aPosition, NULL, true ) )
- return true;
+ if( item->Type() != SCH_LINE_T )
+ continue;
+
+ if( item->GetLayer() != LAYER_WIRE )
+ continue;
+
+ if( item->HitTest( aPosition, 0 ) )
+ lines.push_back( (SCH_LINE*) item );
+ }
+
+ BOOST_FOREACH( SCH_LINE* line, lines)
+ {
+ if( !line->IsEndPoint( aPosition ) )
+ has_line = true;
+ else
+ end_count++;
+ BOOST_REVERSE_FOREACH( SCH_LINE* second_line, lines )
+ {
+ if( line == second_line )
+ break;
+ if( line->IsEndPoint( second_line->GetStartPoint() )
+ && line->IsEndPoint( second_line->GetEndPoint() ) )
+ end_count--;
+ if( !line->IsParallel( second_line ) )
+ has_nonparallel = true;
+ }
}
+ int has_pin = !!( GetPin( aPosition, NULL, true ) );
+
+ // If there is line intersecting a pin or non-parallel end
+ if( has_pin && ( has_line || end_count > 1 ) )
+ return true;
+ // If there is at least one segment that ends on a non-parallel line or
+ // junction of two other lines
+ if( has_nonparallel && (has_line || end_count > 2 ) )
+ return true;
+
return false;
}
@@ -1098,30 +1138,6 @@ int SCH_SCREEN::GetConnection( const wxPoint& aPosition, PICKED_ITEMS_LIST& aLis
}
}
- // Get redundant junctions (junctions which connect < 3 end wires
- // and no pin)
- for( item = m_drawList.begin(); item; item = item->Next() )
- {
- if( item->GetFlags() & STRUCT_DELETED )
- continue;
-
- if( !(item->GetFlags() & CANDIDATE) )
- continue;
-
- if( item->Type() != SCH_JUNCTION_T )
- continue;
-
- SCH_JUNCTION* junction = (SCH_JUNCTION*) item;
-
- if( CountConnectedItems( junction->GetPosition(), false ) <= 2 )
- {
- item->SetFlags( STRUCT_DELETED );
-
- ITEM_PICKER picker( item, UR_DELETED );
- aList.PushItem( picker );
- }
- }
-
for( item = m_drawList.begin(); item; item = item->Next() )
{
if( item->GetFlags() & STRUCT_DELETED )
@@ -1132,7 +1148,7 @@ int SCH_SCREEN::GetConnection( const wxPoint& aPosition, PICKED_ITEMS_LIST& aLis
tmp = GetWireOrBus( ( (SCH_TEXT*) item )->GetPosition() );
- if( tmp && tmp->GetFlags() & STRUCT_DELETED )
+ if( tmp && ( tmp->GetFlags() & STRUCT_DELETED ) )
{
item->SetFlags( STRUCT_DELETED );
diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp
index 37a9fd652..b9dad1587 100644
--- a/eeschema/schedit.cpp
+++ b/eeschema/schedit.cpp
@@ -190,6 +190,7 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_POPUP_SCH_DELETE_CONNECTION:
m_canvas->MoveCursorToCrossHair();
DeleteConnection( id == ID_POPUP_SCH_DELETE_CONNECTION );
+ SchematicCleanUp( true );
screen->SetCurItem( NULL );
SetRepeatItem( NULL );
@@ -214,6 +215,7 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
break;
DeleteItem( item );
+ SchematicCleanUp( true );
screen->SetCurItem( NULL );
SetRepeatItem( NULL );
screen->TestDanglingEnds();
@@ -630,6 +632,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool aFullConnection )
if( screen->GetConnection( pos, pickList, aFullConnection ) != 0 )
{
DeleteItemsInList( pickList );
+ SchematicCleanUp( true );
OnModify();
}
}
diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp
index ea0043ad9..f2f28d51b 100644
--- a/eeschema/schframe.cpp
+++ b/eeschema/schframe.cpp
@@ -1443,7 +1443,16 @@ void SCH_EDIT_FRAME::addCurrentItemToList( bool aRedraw )
m_canvas->EndMouseCapture();
if( item->IsConnectable() )
+ {
+ std::vector< wxPoint > pts;
+ item->GetConnectionPoints( pts );
+ for( auto i : pts )
+ {
+ if( screen->IsJunctionNeeded( i, true ) )
+ AddJunction( i, true );
+ }
screen->TestDanglingEnds();
+ }
if( aRedraw )
GetCanvas()->Refresh();
diff --git a/eeschema/schframe.h b/eeschema/schframe.h
index 7f7aa260d..90366584d 100644
--- a/eeschema/schframe.h
+++ b/eeschema/schframe.h
@@ -937,19 +937,25 @@ private:
SCH_JUNCTION* AddJunction( const wxPoint& aPosition, bool aPutInUndoList = false );
/**
- * Function SaveWireImage
- * saves a copy of the current wire image in the undo list
+ * Save a copy of the current wire image in the undo list.
*/
void SaveWireImage();
/**
- * Function SchematicCleanUp
- * performs routine schematic cleaning including breaking wire and buses and
+ * Collects a unique list of all possible connection points in the schematic.
+ *
+ * @param aConnections vector of connections
+ */
+ void GetSchematicConnections( std::vector< wxPoint >& aConnections );
+
+ /**
+ * Performs routine schematic cleaning including breaking wire and buses and
* deleting identical objects superimposed on top of each other.
*
+ * @param aAppend The changes to the schematic should be appended to the previous undo
* @return True if any schematic clean up was performed.
*/
- bool SchematicCleanUp();
+ bool SchematicCleanUp( bool aAppend = false );
/**
* Start moving \a aItem using the mouse.
@@ -1128,6 +1134,15 @@ public:
*/
void DeleteItemsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend = false );
+ /**
+ * Adds junctions if needed to each item in the list after they have been
+ * moved.
+ *
+ * @param aItemsList The list of items to check
+ * @param aAppend True if we are updating a previous commit
+ */
+ void CheckJunctionsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend = false );
+
int GetLabelIncrement() const { return m_repeatLabelDelta; }
private:
--
2.11.0
From b0127f18d746ab77de20b40f9e1564562e5b2131 Mon Sep 17 00:00:00 2001
From: Seth Hillbrand <hillbrand@xxxxxxxxxxx>
Date: Thu, 26 Oct 2017 08:25:47 -0700
Subject: [PATCH 8/9] Eeschema: Moving BreakSegment into SCH_EDIT_FRAME
BreakSegment now breaks a known segment and BreakSegments
breaks all segments. This allows functions to break a
segment without needing to iterate through the whole list.
---
eeschema/block.cpp | 3 --
eeschema/bus-wire-junction.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++
eeschema/class_sch_screen.h | 17 ---------
eeschema/sch_screen.cpp | 59 -----------------------------
eeschema/schedit.cpp | 23 +----------
eeschema/schframe.h | 35 +++++++++++++++++
6 files changed, 123 insertions(+), 100 deletions(-)
diff --git a/eeschema/block.cpp b/eeschema/block.cpp
index f0a52f795..f4aa8517c 100644
--- a/eeschema/block.cpp
+++ b/eeschema/block.cpp
@@ -228,9 +228,6 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
case BLOCK_DRAG:
case BLOCK_DRAG_ITEM: // Drag from a drag command
- GetScreen()->BreakSegmentsOnJunctions();
- // fall through
-
case BLOCK_MOVE:
case BLOCK_DUPLICATE:
if( block->GetCommand() == BLOCK_DRAG_ITEM &&
diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp
index ea215c302..f3e2f2171 100644
--- a/eeschema/bus-wire-junction.cpp
+++ b/eeschema/bus-wire-junction.cpp
@@ -417,6 +417,30 @@ void SCH_EDIT_FRAME::DeleteCurrentSegment( wxDC* DC )
}
+void SCH_EDIT_FRAME::SaveWireImage()
+{
+ DLIST< SCH_ITEM > oldWires;
+
+ oldWires.SetOwnership( false ); // Prevent DLIST for deleting items in destructor.
+ GetScreen()->ExtractWires( oldWires, true );
+
+ if( oldWires.GetCount() != 0 )
+ {
+ 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 );
+ }
+}
+
+
bool SCH_EDIT_FRAME::SchematicCleanUp()
{
bool modified = false;
@@ -465,6 +489,68 @@ bool SCH_EDIT_FRAME::SchematicCleanUp()
return modified;
}
+bool SCH_EDIT_FRAME::BreakSegment( SCH_LINE *aSegment, const wxPoint& aPoint, bool aAppend )
+{
+ if( !IsPointOnSegment( aSegment->GetStartPoint(), aSegment->GetEndPoint(), aPoint )
+ || aSegment->IsEndPoint( aPoint ) )
+ return false;
+
+ SaveCopyInUndoList( aSegment, UR_CHANGED, aAppend );
+ SCH_LINE* newSegment = new SCH_LINE( *aSegment );
+ SaveCopyInUndoList( newSegment, UR_NEW, true );
+
+ newSegment->SetStartPoint( aPoint );
+ aSegment->SetEndPoint( aPoint );
+ GetScreen()->Append( newSegment );
+
+ return true;
+}
+
+
+bool SCH_EDIT_FRAME::BreakSegments( const wxPoint& aPoint, bool aAppend )
+{
+ bool brokenSegments = false;
+
+ for( SCH_ITEM* segment = GetScreen()->GetDrawItems(); segment; segment = segment->Next() )
+ {
+ if( ( segment->Type() != SCH_LINE_T ) || ( segment->GetLayer() == LAYER_NOTES ) )
+ continue;
+
+ brokenSegments |= BreakSegment( (SCH_LINE*) segment, aPoint, aAppend || brokenSegments );
+ }
+
+ return brokenSegments;
+}
+
+
+bool SCH_EDIT_FRAME::BreakSegmentsOnJunctions( bool aAppend )
+{
+ bool brokenSegments = false;
+
+ for( SCH_ITEM* item = GetScreen()->GetDrawItems(); item; item = item->Next() )
+ {
+ if( item->Type() == SCH_JUNCTION_T )
+ {
+ SCH_JUNCTION* junction = ( SCH_JUNCTION* ) item;
+
+ if( BreakSegments( junction->GetPosition(), brokenSegments || aAppend ) )
+ brokenSegments = true;
+ }
+ else
+ {
+ SCH_BUS_ENTRY_BASE* busEntry = dynamic_cast<SCH_BUS_ENTRY_BASE*>( item );
+ if( busEntry )
+ {
+ if( BreakSegments( busEntry->GetPosition(), brokenSegments || aAppend )
+ || BreakSegments( busEntry->m_End(), brokenSegments || aAppend ) )
+ brokenSegments = true;
+ }
+ }
+ }
+
+ return brokenSegments;
+}
+
SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( const wxPoint& aPosition,
bool aPutInUndoList )
diff --git a/eeschema/class_sch_screen.h b/eeschema/class_sch_screen.h
index 7bd647ff5..dd11205e0 100644
--- a/eeschema/class_sch_screen.h
+++ b/eeschema/class_sch_screen.h
@@ -308,23 +308,6 @@ public:
*/
int GetConnection( const wxPoint& aPosition, PICKED_ITEMS_LIST& aList, bool aFullConnection );
- /**
- * Checks every wire and bus for a intersection at \a aPoint and break into two segments
- * at \a aPoint if an intersection is found.
- *
- * @param aPoint Test this point for an intersection.
- * @return True if any wires or buses were broken.
- */
- bool BreakSegment( const wxPoint& aPoint );
-
- /**
- * Tests all junctions and bus entries in the schematic for intersections with wires and
- * buses and breaks any intersections into multiple segments.
- *
- * @return True if any wires or buses were broken.
- */
- bool BreakSegmentsOnJunctions();
-
/* full undo redo management : */
// use BASE_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aItem )
// use BASE_SCREEN::PushCommandToRedoList( PICKED_ITEMS_LIST* aItem )
diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp
index 11837dc80..c263787d7 100644
--- a/eeschema/sch_screen.cpp
+++ b/eeschema/sch_screen.cpp
@@ -845,64 +845,6 @@ bool SCH_SCREEN::TestDanglingEnds()
}
-bool SCH_SCREEN::BreakSegment( const wxPoint& aPoint )
-{
- SCH_LINE* segment;
- SCH_LINE* newSegment;
- bool brokenSegments = false;
-
- for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
- {
- if( (item->Type() != SCH_LINE_T) || (item->GetLayer() == LAYER_NOTES) )
- continue;
-
- segment = (SCH_LINE*) item;
-
- if( !segment->HitTest( aPoint, 0 ) || segment->IsEndPoint( aPoint ) )
- continue;
-
- // Break the segment at aPoint and create a new segment.
- newSegment = new SCH_LINE( *segment );
- newSegment->SetStartPoint( aPoint );
- segment->SetEndPoint( aPoint );
- m_drawList.Insert( newSegment, segment->Next() );
- item = newSegment;
- brokenSegments = true;
- }
-
- return brokenSegments;
-}
-
-
-bool SCH_SCREEN::BreakSegmentsOnJunctions()
-{
- bool brokenSegments = false;
-
- for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
- {
- if( item->Type() == SCH_JUNCTION_T )
- {
- SCH_JUNCTION* junction = ( SCH_JUNCTION* ) item;
-
- if( BreakSegment( junction->GetPosition() ) )
- brokenSegments = true;
- }
- else
- {
- SCH_BUS_ENTRY_BASE* busEntry = dynamic_cast<SCH_BUS_ENTRY_BASE*>( item );
- if( busEntry )
- {
- if( BreakSegment( busEntry->GetPosition() )
- || BreakSegment( busEntry->m_End() ) )
- brokenSegments = true;
- }
- }
- }
-
- return brokenSegments;
-}
-
-
int SCH_SCREEN::GetNode( const wxPoint& aPosition, EDA_ITEMS& aList )
{
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
@@ -1047,7 +989,6 @@ int SCH_SCREEN::GetConnection( const wxPoint& aPosition, PICKED_ITEMS_LIST& aLis
// Clear flags member for all items.
ClearDrawingState();
- BreakSegmentsOnJunctions();
if( GetNode( aPosition, list ) == 0 )
return 0;
diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp
index 61d9bf6e8..37a9fd652 100644
--- a/eeschema/schedit.cpp
+++ b/eeschema/schedit.cpp
@@ -200,28 +200,9 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_POPUP_SCH_BREAK_WIRE:
{
- DLIST< SCH_ITEM > oldWires;
-
- oldWires.SetOwnership( false ); // Prevent DLIST for deleting items in destructor.
+ SaveWireImage();
m_canvas->MoveCursorToCrossHair();
- screen->ExtractWires( oldWires, true );
- screen->BreakSegment( GetCrossHairPosition() );
-
- if( oldWires.GetCount() != 0 )
- {
- 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 );
- }
-
+ BreakSegments( GetCrossHairPosition() );
if( screen->TestDanglingEnds() )
m_canvas->Refresh();
}
diff --git a/eeschema/schframe.h b/eeschema/schframe.h
index 76013d54d..7f7aa260d 100644
--- a/eeschema/schframe.h
+++ b/eeschema/schframe.h
@@ -466,6 +466,35 @@ public:
bool aWarpMouse );
/**
+ * Breaks a single segment into two at the specified point
+ *
+ * @param aSegment Line segment to break
+ * @param aPoint Point at which to break the segment
+ * @param aAppend Add the changes to the previous undo state
+ * @return True if any wires or buses were broken.
+ */
+ bool BreakSegment( SCH_LINE* aSegment, const wxPoint& aPoint, bool aAppend = false );
+
+ /**
+ * Checks every wire and bus for a intersection at \a aPoint and break into two segments
+ * at \a aPoint if an intersection is found.
+ *
+ * @param aPoint Test this point for an intersection.
+ * @param aAppend Add the changes to the previous undo state
+ * @return True if any wires or buses were broken.
+ */
+ bool BreakSegments( const wxPoint& aPoint, bool aAppend = false );
+
+ /**
+ * Tests all junctions and bus entries in the schematic for intersections with wires and
+ * buses and breaks any intersections into multiple segments.
+ *
+ * @param aAppend Add the changes to the previous undo state
+ * @return True if any wires or buses were broken.
+ */
+ bool BreakSegmentsOnJunctions( bool aApped = false );
+
+ /**
* Send a message to Pcbnew via a socket connection.
*
* Commands are:
@@ -908,6 +937,12 @@ private:
SCH_JUNCTION* AddJunction( const wxPoint& aPosition, bool aPutInUndoList = false );
/**
+ * Function SaveWireImage
+ * saves a copy of the current wire image in the undo list
+ */
+ void SaveWireImage();
+
+ /**
* Function SchematicCleanUp
* performs routine schematic cleaning including breaking wire and buses and
* deleting identical objects superimposed on top of each other.
--
2.11.0
From 1cb763c760b15d8d6f561beb1e8e239ce582d992 Mon Sep 17 00:00:00 2001
From: Seth Hillbrand <hillbrand@xxxxxxxxxxx>
Date: Thu, 16 Nov 2017 12:39:59 -0800
Subject: [PATCH 7/9] Eeschema: Removing DC dependencies
---
eeschema/bus-wire-junction.cpp | 16 ++++++----------
eeschema/onleftclick.cpp | 6 +++---
eeschema/schedit.cpp | 4 ++--
eeschema/schframe.h | 7 +++----
4 files changed, 14 insertions(+), 19 deletions(-)
diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp
index 410f830f6..ea215c302 100644
--- a/eeschema/bus-wire-junction.cpp
+++ b/eeschema/bus-wire-junction.cpp
@@ -248,7 +248,7 @@ void SCH_EDIT_FRAME::BeginSegment( wxDC* DC, int type )
// Terminate the command if the end point is on a pin, junction, or another wire or bus.
if( GetScreen()->IsTerminalPoint( cursorpos, segment->GetLayer() ) )
{
- EndSegment( DC );
+ EndSegment();
return;
}
@@ -267,7 +267,7 @@ void SCH_EDIT_FRAME::BeginSegment( wxDC* DC, int type )
}
-void SCH_EDIT_FRAME::EndSegment( wxDC* DC )
+void SCH_EDIT_FRAME::EndSegment()
{
SCH_SCREEN* screen = GetScreen();
SCH_LINE* segment = (SCH_LINE*) screen->GetCurItem();
@@ -334,11 +334,11 @@ void SCH_EDIT_FRAME::EndSegment( wxDC* DC )
// A junction could be needed to connect the end point of the last created segment.
if( screen->IsJunctionNeeded( endpoint ) )
- screen->Append( AddJunction( DC, endpoint ) );
+ screen->Append( AddJunction( 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 ) );
+ screen->Append( AddJunction( startPoint ) );
m_canvas->Refresh();
@@ -466,17 +466,13 @@ bool SCH_EDIT_FRAME::SchematicCleanUp()
}
-SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( wxDC* aDC, const wxPoint& aPosition,
+SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( const wxPoint& aPosition,
bool aPutInUndoList )
{
SCH_JUNCTION* junction = new SCH_JUNCTION( aPosition );
SetRepeatItem( junction );
- m_canvas->CrossHairOff( aDC ); // Erase schematic cursor
- junction->Draw( m_canvas, aDC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
- m_canvas->CrossHairOn( aDC ); // Display schematic cursor
-
if( aPutInUndoList )
{
GetScreen()->Append( junction );
@@ -488,7 +484,7 @@ SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( wxDC* aDC, const wxPoint& aPosition,
}
-SCH_NO_CONNECT* SCH_EDIT_FRAME::AddNoConnect( wxDC* aDC, const wxPoint& aPosition )
+SCH_NO_CONNECT* SCH_EDIT_FRAME::AddNoConnect( const wxPoint& aPosition )
{
SCH_NO_CONNECT* no_connect = new SCH_NO_CONNECT( aPosition );
diff --git a/eeschema/onleftclick.cpp b/eeschema/onleftclick.cpp
index ed349001b..2cfc9e045 100644
--- a/eeschema/onleftclick.cpp
+++ b/eeschema/onleftclick.cpp
@@ -120,7 +120,7 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
{
if( GetScreen()->GetItem( gridPosition, 0, SCH_NO_CONNECT_T ) == NULL )
{
- SCH_NO_CONNECT* no_connect = AddNoConnect( aDC, gridPosition );
+ SCH_NO_CONNECT* no_connect = AddNoConnect( gridPosition );
SetRepeatItem( no_connect );
GetScreen()->SetCurItem( no_connect );
m_canvas->SetAutoPanRequest( true );
@@ -137,7 +137,7 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
{
if( GetScreen()->GetItem( gridPosition, 0, SCH_JUNCTION_T ) == NULL )
{
- SCH_JUNCTION* junction = AddJunction( aDC, gridPosition, true );
+ SCH_JUNCTION* junction = AddJunction( gridPosition );
SetRepeatItem( junction );
GetScreen()->SetCurItem( junction );
m_canvas->SetAutoPanRequest( true );
@@ -442,7 +442,7 @@ void SCH_EDIT_FRAME::OnLeftDClick( wxDC* aDC, const wxPoint& aPosition )
case ID_WIRE_BUTT:
case ID_LINE_COMMENT_BUTT:
if( item && item->IsNew() )
- EndSegment( aDC );
+ EndSegment();
break;
}
diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp
index 80b17570c..61d9bf6e8 100644
--- a/eeschema/schedit.cpp
+++ b/eeschema/schedit.cpp
@@ -169,7 +169,7 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_POPUP_END_LINE:
m_canvas->MoveCursorToCrossHair();
- EndSegment( &dc );
+ EndSegment();
break;
case ID_POPUP_SCH_BEGIN_WIRE:
@@ -372,7 +372,7 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_POPUP_SCH_ADD_JUNCTION:
m_canvas->MoveCursorToCrossHair();
- screen->SetCurItem( AddJunction( &dc, GetCrossHairPosition(), true ) );
+ screen->SetCurItem( AddJunction( GetCrossHairPosition() ) );
if( screen->TestDanglingEnds() )
m_canvas->Refresh();
diff --git a/eeschema/schframe.h b/eeschema/schframe.h
index a583ab46f..76013d54d 100644
--- a/eeschema/schframe.h
+++ b/eeschema/schframe.h
@@ -897,16 +897,15 @@ private:
/**
* Add no connect item to the current schematic sheet at \a aPosition.
*
- * @param aDC The device context to draw the no connect to.
* @param aPosition The position in logical (drawing) units to add the no connect.
* @return The no connect item added.
*/
- SCH_NO_CONNECT* AddNoConnect( wxDC* aDC, const wxPoint& aPosition );
+ SCH_NO_CONNECT* AddNoConnect( const wxPoint& aPosition );
/**
* Add a new junction at \a aPosition.
*/
- SCH_JUNCTION* AddJunction( wxDC* aDC, const wxPoint& aPosition, bool aPutInUndoList = false );
+ SCH_JUNCTION* AddJunction( const wxPoint& aPosition, bool aPutInUndoList = false );
/**
* Function SchematicCleanUp
@@ -950,7 +949,7 @@ private:
/**
* Terminate a bus, wire, or line creation.
*/
- void EndSegment( wxDC* DC );
+ void EndSegment();
/**
* Erase the last segment at the current mouse position.
--
2.11.0
From b154352a577ede9e18dbf499be323ccf9f26ce84 Mon Sep 17 00:00:00 2001
From: Seth Hillbrand <hillbrand@xxxxxxxxxxx>
Date: Wed, 25 Oct 2017 15:21:42 -0700
Subject: [PATCH 6/9] Eeschema: Moving SchematicCleanup to SCH_EDIT_FRAME
SchematicCleanup function moved from SCH_SCREEN to
SCH_EDIT_FRAME to allow access to the undo stack as we
are changing the schematic.
---
eeschema/bus-wire-junction.cpp | 53 ++++++++++++++++++++++++++++++++++--
eeschema/class_sch_screen.h | 14 ----------
eeschema/hierarch.cpp | 2 +-
eeschema/project_rescue.cpp | 2 +-
eeschema/sch_screen.cpp | 62 ------------------------------------------
eeschema/schframe.cpp | 2 +-
eeschema/schframe.h | 10 +++++++
7 files changed, 64 insertions(+), 81 deletions(-)
diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp
index fa0175463..410f830f6 100644
--- a/eeschema/bus-wire-junction.cpp
+++ b/eeschema/bus-wire-junction.cpp
@@ -330,7 +330,7 @@ void SCH_EDIT_FRAME::EndSegment( wxDC* DC )
screen->Append( s_wires );
// Correct and remove segments that need to be merged.
- screen->SchematicCleanUp();
+ SchematicCleanUp();
// A junction could be needed to connect the end point of the last created segment.
if( screen->IsJunctionNeeded( endpoint ) )
@@ -417,6 +417,55 @@ void SCH_EDIT_FRAME::DeleteCurrentSegment( wxDC* DC )
}
+bool SCH_EDIT_FRAME::SchematicCleanUp()
+{
+ bool modified = false;
+
+ for( SCH_ITEM* item = GetScreen()->GetDrawItems() ; item; item = item->Next() )
+ {
+ if( ( item->Type() != SCH_LINE_T ) && ( item->Type() != SCH_JUNCTION_T ) )
+ continue;
+
+ bool restart;
+
+ for( SCH_ITEM* testItem = item->Next(); testItem; testItem = restart ? GetScreen()->GetDrawItems() : testItem->Next() )
+ {
+ restart = false;
+
+ if( ( item->Type() == SCH_LINE_T ) && ( testItem->Type() == SCH_LINE_T ) )
+ {
+ SCH_LINE* line = (SCH_LINE*) item;
+
+ if( line->MergeOverlap( (SCH_LINE*) testItem ) )
+ {
+ // Keep the current flags, because the deleted segment can be flagged.
+ item->SetFlags( testItem->GetFlags() );
+ DeleteItem( testItem );
+ restart = true;
+ modified = true;
+ }
+ }
+ else if ( ( ( item->Type() == SCH_JUNCTION_T )
+ && ( testItem->Type() == SCH_JUNCTION_T ) ) && ( testItem != item ) )
+ {
+ if ( testItem->HitTest( item->GetPosition() ) )
+ {
+ // Keep the current flags, because the deleted segment can be flagged.
+ item->SetFlags( testItem->GetFlags() );
+ DeleteItem( testItem );
+ restart = true;
+ modified = true;
+ }
+ }
+ }
+ }
+
+ GetScreen()->TestDanglingEnds();
+
+ return modified;
+}
+
+
SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( wxDC* aDC, const wxPoint& aPosition,
bool aPutInUndoList )
{
@@ -445,7 +494,7 @@ SCH_NO_CONNECT* SCH_EDIT_FRAME::AddNoConnect( wxDC* aDC, const wxPoint& aPositio
SetRepeatItem( no_connect );
GetScreen()->Append( no_connect );
- GetScreen()->SchematicCleanUp();
+ SchematicCleanUp();
OnModify();
m_canvas->Refresh();
SaveCopyInUndoList( no_connect, UR_NEW );
diff --git a/eeschema/class_sch_screen.h b/eeschema/class_sch_screen.h
index 92c564d83..7bd647ff5 100644
--- a/eeschema/class_sch_screen.h
+++ b/eeschema/class_sch_screen.h
@@ -262,16 +262,7 @@ public:
bool CheckIfOnDrawList( SCH_ITEM* st );
/**
- * Perform routine schematic cleaning including breaking wire and buses and
- * deleting identical objects superimposed on top of each other.
- *
- * @return True if any schematic clean up was performed.
- */
- bool SchematicCleanUp();
-
- /**
* Test all of the connectable objects in the schematic for unused connection points.
- *
* @return True if any connection state changes were made.
*/
bool TestDanglingEnds();
@@ -542,11 +533,6 @@ public:
void ClearAnnotation();
/**
- * Merge and break wire segments in the entire schematic hierarchy.
- */
- void SchematicCleanUp();
-
- /**
* Test all sheet and component objects in the schematic for duplicate time stamps
* and replaces them as necessary.
* Time stamps must be unique in order for complex hierarchies know which components go
diff --git a/eeschema/hierarch.cpp b/eeschema/hierarch.cpp
index d66aa4ea9..c41c82164 100644
--- a/eeschema/hierarch.cpp
+++ b/eeschema/hierarch.cpp
@@ -299,7 +299,7 @@ void SCH_EDIT_FRAME::DisplayCurrentSheet()
screen->m_FirstRedraw = false;
SetCrossHairPosition( GetScrollCenterPosition() );
m_canvas->MoveCursorToCrossHair();
- screen->SchematicCleanUp();
+ SchematicCleanUp();
}
else
{
diff --git a/eeschema/project_rescue.cpp b/eeschema/project_rescue.cpp
index ed2485d58..0af8db517 100644
--- a/eeschema/project_rescue.cpp
+++ b/eeschema/project_rescue.cpp
@@ -556,7 +556,7 @@ bool SCH_EDIT_FRAME::rescueProject( RESCUER& aRescuer, bool aRunningOnDemand )
viewer->ReCreateListLib();
// Clean up wire ends
- GetScreen()->SchematicCleanUp();
+ SchematicCleanUp();
m_canvas->Refresh( true );
OnModify();
diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp
index edc90bc4b..11837dc80 100644
--- a/eeschema/sch_screen.cpp
+++ b/eeschema/sch_screen.cpp
@@ -435,55 +435,6 @@ bool SCH_SCREEN::IsTerminalPoint( const wxPoint& aPosition, int aLayer )
}
-bool SCH_SCREEN::SchematicCleanUp()
-{
- bool modified = false;
-
- for( SCH_ITEM* item = m_drawList.begin() ; item; item = item->Next() )
- {
- if( ( item->Type() != SCH_LINE_T ) && ( item->Type() != SCH_JUNCTION_T ) )
- continue;
-
- bool restart;
-
- for( SCH_ITEM* testItem = item->Next(); testItem; testItem = restart ? m_drawList.begin() : testItem->Next() )
- {
- restart = false;
-
- if( ( item->Type() == SCH_LINE_T ) && ( testItem->Type() == SCH_LINE_T ) )
- {
- SCH_LINE* line = (SCH_LINE*) item;
-
- if( line->MergeOverlap( (SCH_LINE*) testItem ) )
- {
- // Keep the current flags, because the deleted segment can be flagged.
- item->SetFlags( testItem->GetFlags() );
- DeleteItem( testItem );
- restart = true;
- modified = true;
- }
- }
- else if ( ( ( item->Type() == SCH_JUNCTION_T )
- && ( testItem->Type() == SCH_JUNCTION_T ) ) && ( testItem != item ) )
- {
- if ( testItem->HitTest( item->GetPosition() ) )
- {
- // Keep the current flags, because the deleted segment can be flagged.
- item->SetFlags( testItem->GetFlags() );
- DeleteItem( testItem );
- restart = true;
- modified = true;
- }
- }
- }
- }
-
- TestDanglingEnds();
-
- return modified;
-}
-
-
void SCH_SCREEN::UpdateSymbolLinks( bool aForce )
{
// Initialize or reinitialize the pointer to the LIB_PART for each component
@@ -1375,19 +1326,6 @@ void SCH_SCREENS::ClearAnnotation()
m_screens[i]->ClearAnnotation( NULL );
}
-
-void SCH_SCREENS::SchematicCleanUp()
-{
- for( size_t i = 0; i < m_screens.size(); i++ )
- {
- // if wire list has changed, delete the undo/redo list to avoid
- // pointer problems with deleted data.
- if( m_screens[i]->SchematicCleanUp() )
- m_screens[i]->ClearUndoRedoList();
- }
-}
-
-
int SCH_SCREENS::ReplaceDuplicateTimeStamps()
{
EDA_ITEMS items;
diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp
index c6808858a..ea0043ad9 100644
--- a/eeschema/schframe.cpp
+++ b/eeschema/schframe.cpp
@@ -1249,7 +1249,7 @@ void SCH_EDIT_FRAME::OnOpenLibraryEditor( wxCommandEvent& event )
libeditFrame->LoadComponentAndSelectLib( id );
}
- GetScreen()->SchematicCleanUp();
+ SchematicCleanUp();
m_canvas->Refresh();
}
diff --git a/eeschema/schframe.h b/eeschema/schframe.h
index 1e3e46dd8..a583ab46f 100644
--- a/eeschema/schframe.h
+++ b/eeschema/schframe.h
@@ -909,6 +909,15 @@ private:
SCH_JUNCTION* AddJunction( wxDC* aDC, const wxPoint& aPosition, bool aPutInUndoList = false );
/**
+ * Function SchematicCleanUp
+ * performs routine schematic cleaning including breaking wire and buses and
+ * deleting identical objects superimposed on top of each other.
+ *
+ * @return True if any schematic clean up was performed.
+ */
+ bool SchematicCleanUp();
+
+ /**
* Start moving \a aItem using the mouse.
*
* @param aItem A pointer to an SCH_ITEM to move.
@@ -1072,6 +1081,7 @@ public:
* Remove \a aItem from the current screen and saves it in the undo list.
*
* @param aItem The item to remove from the current screen.
+ * @param aAppend True if we are updating a previous Undo state
*/
void DeleteItem( SCH_ITEM* aItem, bool aAppend = false );
--
2.11.0
From 0532cb7eee1b14f576308f9c3365699d9893f7a4 Mon Sep 17 00:00:00 2001
From: Seth Hillbrand <hillbrand@xxxxxxxxxxx>
Date: Tue, 31 Oct 2017 12:33:00 -0700
Subject: [PATCH 5/9] Eeschema: Remove zero-length wires in RemoveBacktracks
RemoveBacktracks call removes zero-length wires as well
---
eeschema/bus-wire-junction.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp
index 528d09d68..fa0175463 100644
--- a/eeschema/bus-wire-junction.cpp
+++ b/eeschema/bus-wire-junction.cpp
@@ -74,6 +74,12 @@ static void RemoveBacktracks( DLIST<SCH_ITEM>& aWires )
SCH_LINE *line = static_cast<SCH_LINE*>( p );
p = line->Next();
+ if( line->IsNull() )
+ {
+ delete s_wires.Remove( line );
+ continue;
+ }
+
if( !last_lines.empty() )
{
SCH_LINE* last_line = last_lines[last_lines.size() - 1];
--
2.11.0
From f8a9722c1553fdf079c7929c3cdde4229bccfd4d Mon Sep 17 00:00:00 2001
From: Seth Hillbrand <hillbrand@xxxxxxxxxxx>
Date: Fri, 20 Oct 2017 09:31:02 -0700
Subject: [PATCH 4/9] Eeschema: don't cleanup unseen schematics
Changes to the schematic shouldn't be made
where the user isn't looking. Removing the
cleanup in ERC and netlisting prevents
unintended consequences
CHANGE: ERC and Netlist calls do not modify schematic
---
eeschema/dialogs/dialog_erc.cpp | 9 ---------
eeschema/netlist.cpp | 4 ----
2 files changed, 13 deletions(-)
diff --git a/eeschema/dialogs/dialog_erc.cpp b/eeschema/dialogs/dialog_erc.cpp
index 8e811a40d..47c9d686b 100644
--- a/eeschema/dialogs/dialog_erc.cpp
+++ b/eeschema/dialogs/dialog_erc.cpp
@@ -478,15 +478,6 @@ void DIALOG_ERC::TestErc( wxArrayString* aMessagesList )
// Erase all previous DRC markers.
screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC );
- for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() )
- {
- /* Ff wire list has changed, delete Undo Redo list to avoid pointers on deleted
- * data problems.
- */
- if( screen->SchematicCleanUp() )
- screen->ClearUndoRedoList();
- }
-
/* Test duplicate sheet names inside a given sheet, one cannot have sheets with
* duplicate names (file names can be duplicated).
*/
diff --git a/eeschema/netlist.cpp b/eeschema/netlist.cpp
index 6252f27c4..ef5d0a5f5 100644
--- a/eeschema/netlist.cpp
+++ b/eeschema/netlist.cpp
@@ -83,9 +83,6 @@ bool SCH_EDIT_FRAME::prepareForNetlist()
return false;
}
- // Cleanup the entire hierarchy
- schematic.SchematicCleanUp();
-
return true;
}
@@ -123,7 +120,6 @@ bool SCH_EDIT_FRAME::CreateNetlist( int aFormat, const wxString& aFullFileName,
schematic.UpdateSymbolLinks();
SCH_SHEET_LIST sheets( g_RootSheet );
sheets.AnnotatePowerSymbols();
- schematic.SchematicCleanUp();
}
std::unique_ptr<NETLIST_OBJECT_LIST> connectedItemsList( BuildNetListBase() );
--
2.11.0
From e8bf685a8f97d221a0986368b9b587e269cdd7a1 Mon Sep 17 00:00:00 2001
From: Seth Hillbrand <hillbrand@xxxxxxxxxxx>
Date: Mon, 16 Oct 2017 14:38:57 -0700
Subject: [PATCH 3/9] Eeschema: Add two utility functions to sch_line
Add IsSameQuandrant and IsParallel functions
---
eeschema/sch_line.cpp | 36 ++++++++++++++++++++++++++++++++++++
eeschema/sch_line.h | 12 ++++++++++++
2 files changed, 48 insertions(+)
diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp
index 4e3246c2a..7a05fee98 100644
--- a/eeschema/sch_line.cpp
+++ b/eeschema/sch_line.cpp
@@ -352,6 +352,42 @@ void SCH_LINE::Rotate( wxPoint aPosition )
}
+bool SCH_LINE::IsSameQuadrant( SCH_LINE* aLine, const wxPoint& aPosition )
+{
+ wxPoint first;
+ wxPoint second;
+
+ if( m_start == aPosition )
+ first = m_end - aPosition;
+ else if( m_end == aPosition )
+ first = m_start - aPosition;
+ else
+ return false;
+
+ if( aLine->m_start == aPosition )
+ second = aLine->m_end - aPosition;
+ else if( aLine->m_end == aPosition )
+ second = aLine->m_start - aPosition;
+ else
+ return false;
+
+ return (std::signbit( first.x ) == std::signbit( second.x ) &&
+ std::signbit( first.y ) == std::signbit( second.y ) );
+}
+
+
+bool SCH_LINE::IsParallel( SCH_LINE* aLine )
+{
+ wxCHECK_MSG( aLine != NULL && aLine->Type() == SCH_LINE_T, false,
+ wxT( "Cannot test line segment for overlap." ) );
+
+ wxPoint firstSeg = m_end - m_start;
+ wxPoint secondSeg = aLine->m_end - aLine->m_start;
+
+ // Use long long here to avoid overflow in calculations
+ return !( (long long) firstSeg.x * secondSeg.y - (long long) firstSeg.y * secondSeg.x );
+}
+
bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
{
auto less = []( const wxPoint& lhs, const wxPoint& rhs ) -> bool
diff --git a/eeschema/sch_line.h b/eeschema/sch_line.h
index ac84a2a6c..6b7594c31 100644
--- a/eeschema/sch_line.h
+++ b/eeschema/sch_line.h
@@ -142,6 +142,18 @@ public:
*/
bool MergeOverlap( SCH_LINE* aLine );
+ /**
+ * Check if two lines are in the same quadrant as each other, using a reference point as
+ * the origin
+ *
+ * @param aLine - Line to compare
+ * @param aPosition - Point to reference against lines
+ * @return true if lines are mostly in different quadrants of aPosition, false otherwise
+ */
+ bool IsSameQuadrant( SCH_LINE* aLine, const wxPoint& aPosition );
+
+ bool IsParallel( SCH_LINE* aLine );
+
void GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList ) override;
bool IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemList ) override;
--
2.11.0
From 4e2243f339440d9d302b984fcdac7468287eb391 Mon Sep 17 00:00:00 2001
From: Seth Hillbrand <hillbrand@xxxxxxxxxxx>
Date: Thu, 12 Oct 2017 16:41:25 -0700
Subject: [PATCH 2/9] Eeschema: Unify delete operations
DeleteItemsInList now shares the code for DeleteItem.
SCH_FRAME::DeleteItem removes junctions that are no longer needed.
---
eeschema/block.cpp | 4 +--
eeschema/operations_on_items_lists.cpp | 56 ++++++++++++++++++++++------------
eeschema/schedit.cpp | 2 +-
eeschema/schframe.h | 11 ++++++-
4 files changed, 49 insertions(+), 24 deletions(-)
diff --git a/eeschema/block.cpp b/eeschema/block.cpp
index 2d2af403f..f0a52f795 100644
--- a/eeschema/block.cpp
+++ b/eeschema/block.cpp
@@ -272,7 +272,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
if( block->GetCount() )
{
- DeleteItemsInList( m_canvas, block->GetItems() );
+ DeleteItemsInList( block->GetItems() );
OnModify();
}
block->ClearItemsList();
@@ -303,7 +303,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
wxPoint move_vector = -GetScreen()->m_BlockLocate.GetLastCursorPosition();
copyBlockItems( block->GetItems() );
MoveItemsInList( m_blockItems.GetItems(), move_vector );
- DeleteItemsInList( m_canvas, block->GetItems() );
+ DeleteItemsInList( block->GetItems() );
OnModify();
}
diff --git a/eeschema/operations_on_items_lists.cpp b/eeschema/operations_on_items_lists.cpp
index a470c5d6f..ad8313d38 100644
--- a/eeschema/operations_on_items_lists.cpp
+++ b/eeschema/operations_on_items_lists.cpp
@@ -115,10 +115,8 @@ void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMoveVector
}
-void DeleteItemsInList( EDA_DRAW_PANEL* panel, PICKED_ITEMS_LIST& aItemsList )
+void SCH_EDIT_FRAME::DeleteItemsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend )
{
- SCH_SCREEN* screen = (SCH_SCREEN*) panel->GetScreen();
- SCH_EDIT_FRAME* frame = (SCH_EDIT_FRAME*) panel->GetParent();
PICKED_ITEMS_LIST itemsList;
for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
@@ -126,46 +124,64 @@ void DeleteItemsInList( EDA_DRAW_PANEL* panel, PICKED_ITEMS_LIST& aItemsList )
SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
ITEM_PICKER itemWrapper( item, UR_DELETED );
- if( item->Type() == SCH_SHEET_PIN_T )
- {
- /* this item is depending on a sheet, and is not in global list */
- wxMessageBox( wxT( "DeleteItemsInList() err: unexpected SCH_SHEET_PIN_T" ) );
- }
- else
- {
- screen->Remove( item );
+ if( item->GetFlags() & STRUCT_DELETED )
+ continue;
- /* Unlink the structure */
- itemsList.PushItem( itemWrapper );
- }
+ DeleteItem( item, aAppend );
+ aAppend = true;
}
- frame->SaveCopyInUndoList( itemsList, UR_DELETED );
+ GetScreen()->ClearDrawingState();
}
-void SCH_EDIT_FRAME::DeleteItem( SCH_ITEM* aItem )
+void SCH_EDIT_FRAME::DeleteItem( SCH_ITEM* aItem, bool aAppend )
{
wxCHECK_RET( aItem != NULL, wxT( "Cannot delete invalid item." ) );
+ wxCHECK_RET( !( aItem->GetFlags() & STRUCT_DELETED ),
+ wxT( "Cannot delete item that is already deleted." ) );
// Here, aItem is not null.
-
SCH_SCREEN* screen = GetScreen();
if( aItem->Type() == SCH_SHEET_PIN_T )
{
- // This iten is attached to a node, and is not accessible by the global list directly.
+ // This item is attached to a node, and is not accessible by the global list directly.
SCH_SHEET* sheet = (SCH_SHEET*) aItem->GetParent();
wxCHECK_RET( (sheet != NULL) && (sheet->Type() == SCH_SHEET_T),
wxT( "Sheet label has invalid parent item." ) );
- SaveCopyInUndoList( (SCH_ITEM*) sheet, UR_CHANGED );
+ SaveCopyInUndoList( (SCH_ITEM*) sheet, UR_CHANGED, aAppend );
sheet->RemovePin( (SCH_SHEET_PIN*) aItem );
m_canvas->RefreshDrawingRect( sheet->GetBoundingBox() );
}
else
{
+ PICKED_ITEMS_LIST itemsList;
+ ITEM_PICKER picker( aItem, UR_DELETED );
+
+ aItem->SetFlags( STRUCT_DELETED );
+ itemsList.PushItem( picker );
screen->Remove( aItem );
- SaveCopyInUndoList( aItem, UR_DELETED );
+
+ if( aItem->IsConnectable() && aItem->Type() != SCH_JUNCTION_T )
+ {
+ std::vector< wxPoint > pts;
+ aItem->GetConnectionPoints( pts );
+ for( auto point : pts )
+ {
+ SCH_ITEM* junction;
+ if( !screen->IsJunctionNeeded( point )
+ && ( junction = screen->GetItem( point, 0, SCH_JUNCTION_T ) ) )
+ {
+ ITEM_PICKER picker_juction( junction, UR_DELETED );
+ junction->SetFlags( STRUCT_DELETED );
+ itemsList.PushItem( picker_juction );
+ screen->Remove( junction );
+ }
+ }
+ }
+
+ SaveCopyInUndoList( itemsList, UR_DELETED, aAppend );
m_canvas->RefreshDrawingRect( aItem->GetBoundingBox() );
}
}
diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp
index 102f1fcbe..80b17570c 100644
--- a/eeschema/schedit.cpp
+++ b/eeschema/schedit.cpp
@@ -648,7 +648,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool aFullConnection )
if( screen->GetConnection( pos, pickList, aFullConnection ) != 0 )
{
- DeleteItemsInList( m_canvas, pickList );
+ DeleteItemsInList( pickList );
OnModify();
}
}
diff --git a/eeschema/schframe.h b/eeschema/schframe.h
index bd0f08a06..1e3e46dd8 100644
--- a/eeschema/schframe.h
+++ b/eeschema/schframe.h
@@ -1073,7 +1073,16 @@ public:
*
* @param aItem The item to remove from the current screen.
*/
- void DeleteItem( SCH_ITEM* aItem );
+ void DeleteItem( SCH_ITEM* aItem, bool aAppend = false );
+
+ /**
+ * Removes all items (and unused junctions that connect to them) and saves
+ * each in the undo list
+ *
+ * @param aItemsList The list of items to delete
+ * @param aAppend True if we are updating a previous commit
+ */
+ void DeleteItemsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend = false );
int GetLabelIncrement() const { return m_repeatLabelDelta; }
--
2.11.0
From f11455986610fdb716ee75a621fed8051fd240d7 Mon Sep 17 00:00:00 2001
From: Seth Hillbrand <hillbrand@xxxxxxxxxxx>
Date: Thu, 16 Nov 2017 12:36:09 -0800
Subject: [PATCH 1/9] Eeschema: Add 'append' option to undo
Allows eeschema to add elements to previous undo commits,
permitting stacking of changes through multiple calls
---
eeschema/block.cpp | 8 +++----
eeschema/edit_bitmap.cpp | 2 +-
eeschema/schematic_undo_redo.cpp | 47 +++++++++++++++++++++++++++++++++++-----
eeschema/schframe.h | 4 ++++
4 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/eeschema/block.cpp b/eeschema/block.cpp
index b6d0d7824..2d2af403f 100644
--- a/eeschema/block.cpp
+++ b/eeschema/block.cpp
@@ -127,7 +127,7 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
if( m_canvas->IsMouseCaptured() )
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
- SaveCopyInUndoList( block->GetItems(), UR_MOVED, block->GetMoveVector() );
+ SaveCopyInUndoList( block->GetItems(), UR_MOVED, false, block->GetMoveVector() );
MoveItemsInList( block->GetItems(), block->GetMoveVector() );
block->ClearItemsList();
break;
@@ -216,7 +216,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
wxPoint rotationPoint = block->Centre();
rotationPoint = GetNearestGridPosition( rotationPoint );
SetCrossHairPosition( rotationPoint );
- SaveCopyInUndoList( block->GetItems(), UR_ROTATED, rotationPoint );
+ SaveCopyInUndoList( block->GetItems(), UR_ROTATED, false, rotationPoint );
RotateListOfItems( block->GetItems(), rotationPoint );
OnModify();
}
@@ -330,7 +330,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
wxPoint mirrorPoint = block->Centre();
mirrorPoint = GetNearestGridPosition( mirrorPoint );
SetCrossHairPosition( mirrorPoint );
- SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_X, mirrorPoint );
+ SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_X, false, mirrorPoint );
MirrorX( block->GetItems(), mirrorPoint );
OnModify();
}
@@ -349,7 +349,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
wxPoint mirrorPoint = block->Centre();
mirrorPoint = GetNearestGridPosition( mirrorPoint );
SetCrossHairPosition( mirrorPoint );
- SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_Y, mirrorPoint );
+ SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_Y, false, mirrorPoint );
MirrorY( block->GetItems(), mirrorPoint );
OnModify();
}
diff --git a/eeschema/edit_bitmap.cpp b/eeschema/edit_bitmap.cpp
index ad2a2b93a..d49efcda8 100644
--- a/eeschema/edit_bitmap.cpp
+++ b/eeschema/edit_bitmap.cpp
@@ -161,7 +161,7 @@ void SCH_EDIT_FRAME::MoveImage( SCH_BITMAP* aImageItem, wxDC* aDC )
void SCH_EDIT_FRAME::RotateImage( SCH_BITMAP* aItem )
{
if( aItem->GetFlags( ) == 0 )
- SaveCopyInUndoList( aItem, UR_ROTATED, aItem->GetPosition() );
+ SaveCopyInUndoList( aItem, UR_ROTATED, false, aItem->GetPosition() );
aItem->Rotate( aItem->GetPosition() );
OnModify();
diff --git a/eeschema/schematic_undo_redo.cpp b/eeschema/schematic_undo_redo.cpp
index 09a83a6bc..75c1731eb 100644
--- a/eeschema/schematic_undo_redo.cpp
+++ b/eeschema/schematic_undo_redo.cpp
@@ -108,8 +108,11 @@
void SCH_EDIT_FRAME::SaveCopyInUndoList( SCH_ITEM* aItem,
UNDO_REDO_T aCommandType,
+ bool aAppend,
const wxPoint& aTransformPoint )
{
+ PICKED_ITEMS_LIST* commandToUndo = NULL;
+
/* Does not save a null item or a UR_WIRE_IMAGE command type. UR_WIRE_IMAGE commands
* are handled by the overloaded version of SaveCopyInUndoList that takes a reference
* to a PICKED_ITEMS_LIST.
@@ -117,8 +120,14 @@ void SCH_EDIT_FRAME::SaveCopyInUndoList( SCH_ITEM* aItem,
if( aItem == NULL || aCommandType == UR_WIRE_IMAGE )
return;
- PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();
- commandToUndo->m_TransformPoint = aTransformPoint;
+ if( aAppend )
+ commandToUndo = GetScreen()->PopCommandFromUndoList();
+
+ if( !commandToUndo )
+ {
+ commandToUndo = new PICKED_ITEMS_LIST();
+ commandToUndo->m_TransformPoint = aTransformPoint;
+ }
ITEM_PICKER itemWrapper( aItem, aCommandType );
itemWrapper.SetFlags( aItem->GetFlags() );
@@ -160,15 +169,41 @@ void SCH_EDIT_FRAME::SaveCopyInUndoList( SCH_ITEM* aItem,
void SCH_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
UNDO_REDO_T aTypeCommand,
+ bool aAppend,
const wxPoint& aTransformPoint )
{
- PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();
+ PICKED_ITEMS_LIST* commandToUndo = NULL;
+
+ if( !aItemsList.GetCount() )
+ return;
+
+ // Can't append a WIRE IMAGE, so fail to a new undo point
+ if( aAppend && ( aTypeCommand != UR_WIRE_IMAGE ) )
+ {
+ commandToUndo = GetScreen()->PopCommandFromUndoList();
+ if( commandToUndo && commandToUndo->m_Status == UR_WIRE_IMAGE )
+ {
+ GetScreen()->PushCommandToUndoList( commandToUndo );
+ commandToUndo = NULL;
+ }
+ }
- commandToUndo->m_TransformPoint = aTransformPoint;
- commandToUndo->m_Status = aTypeCommand;
+ if( !commandToUndo )
+ {
+ commandToUndo = new PICKED_ITEMS_LIST();
+ commandToUndo->m_TransformPoint = aTransformPoint;
+ commandToUndo->m_Status = aTypeCommand;
+ }
// Copy picker list:
- commandToUndo->CopyList( aItemsList );
+ if( !commandToUndo->GetCount() )
+ commandToUndo->CopyList( aItemsList );
+ else
+ {
+ // Unless we are appending, in which case, get the picker items
+ for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
+ commandToUndo->PushItem( aItemsList.GetItemWrapper( ii) );
+ }
// Verify list, and creates data if needed
for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ )
diff --git a/eeschema/schframe.h b/eeschema/schframe.h
index e80e9bbeb..bd0f08a06 100644
--- a/eeschema/schframe.h
+++ b/eeschema/schframe.h
@@ -1161,11 +1161,13 @@ public:
*
* @param aItemToCopy = the schematic item modified by the command to undo
* @param aTypeCommand = command type (see enum UNDO_REDO_T)
+ * @param aAppend = add the item to the previous undo list
* @param aTransformPoint = the reference point of the transformation,
* for commands like move
*/
void SaveCopyInUndoList( SCH_ITEM* aItemToCopy,
UNDO_REDO_T aTypeCommand,
+ bool aAppend = false,
const wxPoint& aTransformPoint = wxPoint( 0, 0 ) );
/**
@@ -1173,11 +1175,13 @@ public:
*
* @param aItemsList = the list of items modified by the command to undo
* @param aTypeCommand = command type (see enum UNDO_REDO_T)
+ * @param aAppend = add the item to the previous undo list
* @param aTransformPoint = the reference point of the transformation,
* for commands like move
*/
void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
UNDO_REDO_T aTypeCommand,
+ bool aAppend = false,
const wxPoint& aTransformPoint = wxPoint( 0, 0 ) );
private:
--
2.11.0
Follow ups
References
-
[PATCH] Eeschema automatic manage junctions
From: Seth Hillbrand, 2017-10-17
-
Re: [PATCH] Eeschema automatic manage junctions
From: Seth Hillbrand, 2017-10-28
-
Re: [PATCH] Eeschema automatic manage junctions
From: Nick Østergaard, 2017-10-28
-
Re: [PATCH] Eeschema automatic manage junctions
From: Seth Hillbrand, 2017-10-28
-
Re: [PATCH] Eeschema automatic manage junctions
From: Nick Østergaard, 2017-10-28
-
Re: [PATCH] Eeschema automatic manage junctions
From: Seth Hillbrand, 2017-10-29
-
Re: [PATCH] Eeschema automatic manage junctions
From: Seth Hillbrand, 2017-11-02
-
Re: [PATCH] Eeschema automatic manage junctions
From: Kevin Cozens, 2017-11-03
-
Re: [PATCH] Eeschema automatic manage junctions
From: Jon Evans, 2017-11-03
-
Re: [PATCH] Eeschema automatic manage junctions
From: Nick Østergaard, 2017-11-08
-
Re: [PATCH] Eeschema automatic manage junctions
From: Seth Hillbrand, 2017-11-22
-
Re: [PATCH] Eeschema automatic manage junctions
From: Maciej Sumiński, 2017-11-24
-
Re: [PATCH] Eeschema automatic manage junctions
From: Seth Hillbrand, 2017-11-25
-
Re: [PATCH] Eeschema automatic manage junctions
From: Maciej Suminski, 2017-11-25