2011-12-12 14:02:37 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gpisa-lab.inpg.fr
|
|
|
|
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
|
|
|
* Copyright (C) 1992-2011 KiCad Developers, see change_log.txt for contributors.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
2010-11-21 18:28:32 +00:00
|
|
|
/**
|
|
|
|
* @file clean.cpp
|
2011-11-24 19:57:41 +00:00
|
|
|
* @brief functions to clean tracks: remove null lenght and redundant segments
|
2010-11-21 18:28:32 +00:00
|
|
|
*/
|
2007-05-06 16:03:28 +00:00
|
|
|
|
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <fctsys.h>
|
|
|
|
#include <class_drawpanel.h>
|
|
|
|
#include <pcbcommon.h>
|
|
|
|
#include <wxPcbStruct.h>
|
|
|
|
#include <pcbnew.h>
|
|
|
|
#include <class_board.h>
|
|
|
|
#include <class_track.h>
|
2012-09-07 19:29:44 +00:00
|
|
|
#include <connect.h>
|
|
|
|
#include <dialog_cleaning_options.h>
|
2011-09-23 13:57:12 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// Helper class used to clean tracks and vias
|
|
|
|
class TRACKS_CLEANER: CONNECTIONS
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
BOARD * m_Brd;
|
|
|
|
bool m_deleteUnconnectedTracks;
|
|
|
|
bool m_mergeSegments;
|
|
|
|
bool m_cleanVias;
|
|
|
|
|
|
|
|
public:
|
|
|
|
TRACKS_CLEANER( BOARD * aPcb );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the cleanup function.
|
|
|
|
* return true if some item was modified
|
|
|
|
*/
|
|
|
|
bool CleanupBoard();
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
void SetdeleteUnconnectedTracksOpt( bool aDelete )
|
|
|
|
{
|
|
|
|
m_deleteUnconnectedTracks = aDelete;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetMergeSegmentsOpt( bool aMerge )
|
|
|
|
{
|
|
|
|
m_mergeSegments = aMerge;
|
|
|
|
}
|
2007-06-14 05:31:55 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
void SetCleanViasOpt( bool aClean )
|
|
|
|
{
|
|
|
|
m_cleanVias = aClean;
|
|
|
|
}
|
2007-06-14 05:31:55 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
private:
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
/**
|
|
|
|
* Removes redundant vias like vias at same location
|
|
|
|
* or on pad through
|
|
|
|
*/
|
|
|
|
bool clean_vias();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes dangling tracks
|
|
|
|
*/
|
|
|
|
bool deleteUnconnectedTracks();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Merge colinear segments and remove null len segments
|
|
|
|
*/
|
|
|
|
bool clean_segments();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* helper function
|
|
|
|
* Rebuild list of tracks, and connected tracks
|
|
|
|
* this info must be rebuilt when tracks are erased
|
|
|
|
*/
|
|
|
|
void buildTrackConnectionInfo();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* helper function
|
|
|
|
* merge aTrackRef and aCandidate, when possible,
|
|
|
|
* i.e. when they are colinear, same width, and obviously same layer
|
|
|
|
*/
|
2012-09-11 07:33:17 +00:00
|
|
|
TRACK* mergeCollinearSegmentIfPossible( TRACK* aTrackRef,
|
2012-09-07 19:29:44 +00:00
|
|
|
TRACK* aCandidate, int aEndType );
|
|
|
|
};
|
2007-10-19 23:02:11 +00:00
|
|
|
|
2013-03-08 07:29:30 +00:00
|
|
|
/* Install the cleanup dialog frame to know what should be cleaned
|
2007-10-27 18:05:50 +00:00
|
|
|
*/
|
2013-03-08 07:29:30 +00:00
|
|
|
void PCB_EDIT_FRAME::Clean_Pcb()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2010-11-21 18:28:32 +00:00
|
|
|
DIALOG_CLEANING_OPTIONS dlg( this );
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2013-03-06 09:04:27 +00:00
|
|
|
if( dlg.ShowModal() != wxID_OK )
|
|
|
|
return;
|
|
|
|
|
|
|
|
wxBusyCursor( dummy );
|
|
|
|
TRACKS_CLEANER cleaner( GetBoard() );
|
2013-09-18 19:21:11 +00:00
|
|
|
cleaner.SetdeleteUnconnectedTracksOpt( dlg.m_deleteUnconnectedSegm );
|
|
|
|
cleaner.SetMergeSegmentsOpt( dlg.m_mergeSegments );
|
|
|
|
cleaner.SetCleanViasOpt( dlg.m_cleanVias );
|
2013-03-06 09:04:27 +00:00
|
|
|
|
|
|
|
if( cleaner.CleanupBoard() )
|
2012-09-07 19:29:44 +00:00
|
|
|
{
|
2013-03-06 09:04:27 +00:00
|
|
|
// Clear undo and redo lists to avoid inconsistencies between lists
|
|
|
|
GetScreen()->ClearUndoRedoList();
|
|
|
|
SetCurItem( NULL );
|
|
|
|
Compile_Ratsnest( NULL, true );
|
|
|
|
OnModify();
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2011-12-22 13:28:11 +00:00
|
|
|
m_canvas->Refresh( true );
|
2007-06-14 05:31:55 +00:00
|
|
|
}
|
|
|
|
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2007-10-27 18:05:50 +00:00
|
|
|
/* Main cleaning function.
|
|
|
|
* Delete
|
|
|
|
* - Redundant points on tracks (merge aligned segments)
|
|
|
|
* - vias on pad
|
2011-11-24 19:57:41 +00:00
|
|
|
* - null lenght segments
|
2011-09-15 17:58:35 +00:00
|
|
|
* Create segments when track ends are incorrectly connected:
|
2007-10-27 18:05:50 +00:00
|
|
|
* i.e. when a track end covers a pad or a via but is not exactly on the pad or the via center
|
|
|
|
*/
|
2012-09-07 19:29:44 +00:00
|
|
|
bool TRACKS_CLEANER::CleanupBoard()
|
2007-06-14 05:31:55 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
bool modified = false;
|
2010-11-21 18:28:32 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// delete redundant vias
|
|
|
|
if( m_cleanVias && clean_vias() )
|
|
|
|
modified = true;
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// Remove null segments and intermediate points on aligned segments
|
|
|
|
if( m_mergeSegments && clean_segments() )
|
|
|
|
modified = true;
|
2009-08-03 07:55:08 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// Delete dangling tracks
|
|
|
|
if( m_deleteUnconnectedTracks && deleteUnconnectedTracks() )
|
|
|
|
modified = true;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
return modified;
|
|
|
|
}
|
2007-06-14 05:31:55 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
TRACKS_CLEANER::TRACKS_CLEANER( BOARD * aPcb ): CONNECTIONS( aPcb )
|
|
|
|
{
|
|
|
|
m_Brd = aPcb;
|
|
|
|
m_deleteUnconnectedTracks = false;
|
|
|
|
m_mergeSegments = false;
|
2011-09-15 17:58:35 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// Build connections info
|
|
|
|
BuildPadsList();
|
|
|
|
buildTrackConnectionInfo();
|
|
|
|
}
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
void TRACKS_CLEANER::buildTrackConnectionInfo()
|
|
|
|
{
|
|
|
|
BuildTracksCandidatesList( m_Brd->m_Track, NULL);
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// clear flags and variables used in cleanup
|
|
|
|
for( TRACK * track = m_Brd->m_Track; track; track = track->Next() )
|
2010-11-21 18:28:32 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
track->start = NULL;
|
|
|
|
track->end = NULL;
|
|
|
|
track->m_PadsConnected.clear();
|
2013-03-31 13:27:46 +00:00
|
|
|
track->SetState( START_ON_PAD|END_ON_PAD|BUSY, false );
|
2010-11-21 18:28:32 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// Build connections info tracks to pads
|
|
|
|
SearchTracksConnectedToPads();
|
|
|
|
for( TRACK * track = m_Brd->m_Track; track; track = track->Next() )
|
2010-11-21 18:28:32 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
// Mark track if connected to pads
|
|
|
|
for( unsigned jj = 0; jj < track->m_PadsConnected.size(); jj++ )
|
|
|
|
{
|
|
|
|
D_PAD * pad = track->m_PadsConnected[jj];
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( pad->HitTest( track->GetStart() ) )
|
|
|
|
{
|
|
|
|
track->start = pad;
|
2013-03-31 13:27:46 +00:00
|
|
|
track->SetState( START_ON_PAD, true );
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( pad->HitTest( track->GetEnd() ) )
|
|
|
|
{
|
|
|
|
track->end = pad;
|
2013-03-31 13:27:46 +00:00
|
|
|
track->SetState( END_ON_PAD, true );
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
bool TRACKS_CLEANER::clean_vias()
|
2010-11-21 18:28:32 +00:00
|
|
|
{
|
|
|
|
TRACK* next_track;
|
2012-09-07 19:29:44 +00:00
|
|
|
bool modified = false;
|
2010-11-21 18:28:32 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
for( TRACK* track = m_Brd->m_Track; track; track = track->Next() )
|
2010-11-21 18:28:32 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
// Correct via m_End defects (if any)
|
|
|
|
if( track->Type() == PCB_VIA_T )
|
|
|
|
{
|
2013-01-13 00:04:00 +00:00
|
|
|
if( track->GetStart() != track->GetEnd() )
|
|
|
|
track->SetEnd( track->GetStart() );
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
|
|
|
|
2011-12-14 04:29:25 +00:00
|
|
|
if( track->GetShape() != VIA_THROUGH )
|
2010-11-21 18:28:32 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Search and delete others vias at same location
|
|
|
|
TRACK* alt_track = track->Next();
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2010-11-21 18:28:32 +00:00
|
|
|
for( ; alt_track != NULL; alt_track = next_track )
|
|
|
|
{
|
|
|
|
next_track = alt_track->Next();
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2013-01-13 00:04:00 +00:00
|
|
|
if( alt_track->GetShape() != VIA_THROUGH )
|
2010-11-21 18:28:32 +00:00
|
|
|
continue;
|
|
|
|
|
2013-01-13 00:04:00 +00:00
|
|
|
if( alt_track->GetStart() != track->GetStart() )
|
2010-11-21 18:28:32 +00:00
|
|
|
continue;
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// delete via
|
2010-11-21 18:28:32 +00:00
|
|
|
alt_track->UnLink();
|
|
|
|
delete alt_track;
|
2012-09-07 19:29:44 +00:00
|
|
|
modified = true;
|
2010-11-21 18:28:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Delete Via on pads at same location
|
2012-09-07 19:29:44 +00:00
|
|
|
for( TRACK* track = m_Brd->m_Track; track != NULL; track = next_track )
|
2010-11-21 18:28:32 +00:00
|
|
|
{
|
|
|
|
next_track = track->Next();
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2013-01-13 00:04:00 +00:00
|
|
|
if( track->GetShape() != VIA_THROUGH )
|
2010-11-21 18:28:32 +00:00
|
|
|
continue;
|
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// Examine the list of connected pads:
|
|
|
|
// if one pad through is found, the via can be removed
|
|
|
|
for( unsigned ii = 0; ii < track->m_PadsConnected.size(); ii++ )
|
2010-11-21 18:28:32 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
D_PAD * pad = track->m_PadsConnected[ii];
|
|
|
|
|
|
|
|
if( (pad->GetLayerMask() & ALL_CU_LAYERS) == ALL_CU_LAYERS )
|
|
|
|
{
|
|
|
|
// redundant: via delete it
|
|
|
|
track->UnLink();
|
|
|
|
delete track;
|
|
|
|
modified = true;
|
|
|
|
break;
|
|
|
|
}
|
2010-11-21 18:28:32 +00:00
|
|
|
}
|
|
|
|
}
|
2012-09-07 19:29:44 +00:00
|
|
|
|
|
|
|
return modified;
|
2010-11-21 18:28:32 +00:00
|
|
|
}
|
|
|
|
|
2007-05-06 16:03:28 +00:00
|
|
|
|
|
|
|
/*
|
2007-10-27 12:24:09 +00:00
|
|
|
* Delete dangling tracks
|
|
|
|
* Vias:
|
|
|
|
* If a via is only connected to a dangling track, it also will be removed
|
2007-08-10 19:14:51 +00:00
|
|
|
*/
|
2012-09-07 19:29:44 +00:00
|
|
|
bool TRACKS_CLEANER::deleteUnconnectedTracks()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
if( m_Brd->m_Track == NULL )
|
|
|
|
return false;
|
2010-11-21 18:28:32 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
bool modified = false;
|
|
|
|
bool item_erased = true;
|
|
|
|
while( item_erased ) // Iterate when at least one track is deleted
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
item_erased = false;
|
|
|
|
TRACK* next_track;
|
|
|
|
for( TRACK * track = m_Brd->m_Track; track ; track = next_track )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
next_track = track->Next();
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
int flag_erase = 0; //Not connected indicator
|
|
|
|
int type_end = 0;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( track->GetState( START_ON_PAD ) )
|
|
|
|
type_end |= START_ON_PAD;
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( track->GetState( END_ON_PAD ) )
|
|
|
|
type_end |= END_ON_PAD;
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// if the track start point is not connected to a pad,
|
|
|
|
// test if this track start point is connected to another track
|
|
|
|
// For via test, an enhancement could be to test if connected
|
|
|
|
// to 2 items on different layers.
|
|
|
|
// Currently a via must be connected to 2 items, that can be on the same layer
|
2013-03-31 13:27:46 +00:00
|
|
|
LAYER_NUM top_layer, bottom_layer;
|
2012-09-07 19:29:44 +00:00
|
|
|
ZONE_CONTAINER* zone;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( (type_end & START_ON_PAD ) == 0 )
|
|
|
|
{
|
|
|
|
TRACK* other = track->GetTrace( m_Brd->m_Track, NULL, FLG_START );
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( other == NULL ) // Test a connection to zones
|
|
|
|
{
|
|
|
|
if( track->Type() != PCB_VIA_T )
|
|
|
|
{
|
2013-01-13 00:04:00 +00:00
|
|
|
zone = m_Brd->HitTestForAnyFilledArea( track->GetStart(),
|
2013-09-18 19:21:11 +00:00
|
|
|
track->GetLayer(),
|
|
|
|
track->GetLayer(),
|
2014-02-25 10:40:34 +00:00
|
|
|
track->GetNetCode() );
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
((SEGVIA*)track)->LayerPair( &top_layer, &bottom_layer );
|
2013-01-13 00:04:00 +00:00
|
|
|
zone = m_Brd->HitTestForAnyFilledArea( track->GetStart(),
|
2013-09-18 19:21:11 +00:00
|
|
|
top_layer, bottom_layer,
|
2014-02-25 10:40:34 +00:00
|
|
|
track->GetNetCode() );
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
|
|
|
}
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( (other == NULL) && (zone == NULL) )
|
|
|
|
{
|
|
|
|
flag_erase |= 1;
|
|
|
|
}
|
|
|
|
else // segment, via or zone connected to this end
|
|
|
|
{
|
|
|
|
track->start = other;
|
|
|
|
// If a via is connected to this end,
|
|
|
|
// test if this via has a second item connected.
|
|
|
|
// If no, remove it with the current segment
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( other && other->Type() == PCB_VIA_T )
|
|
|
|
{
|
|
|
|
// search for another segment following the via
|
2013-03-28 06:40:19 +00:00
|
|
|
track->SetState( BUSY, true );
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
SEGVIA* via = (SEGVIA*) other;
|
|
|
|
other = via->GetTrace( m_Brd->m_Track, NULL, FLG_START );
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( other == NULL )
|
|
|
|
{
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
via->LayerPair( &top_layer, &bottom_layer );
|
2013-01-13 00:04:00 +00:00
|
|
|
zone = m_Brd->HitTestForAnyFilledArea( via->GetStart(),
|
2013-09-18 19:21:11 +00:00
|
|
|
bottom_layer,
|
|
|
|
top_layer,
|
2014-02-25 10:40:34 +00:00
|
|
|
via->GetNetCode() );
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( (other == NULL) && (zone == NULL) )
|
|
|
|
flag_erase |= 2;
|
2008-11-27 10:12:46 +00:00
|
|
|
|
2013-03-28 06:40:19 +00:00
|
|
|
track->SetState( BUSY, false );
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
2008-11-27 10:12:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// if track end point is not connected to a pad,
|
|
|
|
// test if this track end point is connected to an other track
|
|
|
|
if( (type_end & END_ON_PAD ) == 0 )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
TRACK* other = track->GetTrace( m_Brd->m_Track, NULL, FLG_END );
|
2011-10-01 19:24:27 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( other == NULL ) // Test a connection to zones
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
if( track->Type() != PCB_VIA_T )
|
2008-11-27 10:12:46 +00:00
|
|
|
{
|
2013-01-13 00:04:00 +00:00
|
|
|
zone = m_Brd->HitTestForAnyFilledArea( track->GetEnd(),
|
2013-09-18 19:21:11 +00:00
|
|
|
track->GetLayer(),
|
|
|
|
track->GetLayer(),
|
2014-02-25 10:40:34 +00:00
|
|
|
track->GetNetCode() );
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
((SEGVIA*)track)->LayerPair( &top_layer, &bottom_layer );
|
2013-01-13 00:04:00 +00:00
|
|
|
zone = m_Brd->HitTestForAnyFilledArea( track->GetEnd(),
|
2013-09-18 19:21:11 +00:00
|
|
|
top_layer, bottom_layer,
|
2014-02-25 10:40:34 +00:00
|
|
|
track->GetNetCode() );
|
2008-11-27 10:12:46 +00:00
|
|
|
}
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if ( (other == NULL) && (zone == NULL) )
|
2011-09-15 17:58:35 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
flag_erase |= 0x10;
|
2011-09-15 17:58:35 +00:00
|
|
|
}
|
2012-09-07 19:29:44 +00:00
|
|
|
else // segment, via or zone connected to this end
|
2008-11-27 10:12:46 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
track->end = other;
|
2008-12-04 04:28:11 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// If a via is connected to this end, test if this via has a second item connected
|
|
|
|
// if no, remove it with the current segment
|
2011-10-01 19:24:27 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( other && other->Type() == PCB_VIA_T )
|
|
|
|
{
|
|
|
|
// search for another segment following the via
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2013-03-28 06:40:19 +00:00
|
|
|
track->SetState( BUSY, true );
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
SEGVIA* via = (SEGVIA*) other;
|
|
|
|
other = via->GetTrace( m_Brd->m_Track, NULL, FLG_END );
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( other == NULL )
|
|
|
|
{
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
via->LayerPair( &top_layer, &bottom_layer );
|
2013-01-13 00:04:00 +00:00
|
|
|
zone = m_Brd->HitTestForAnyFilledArea( via->GetEnd(),
|
2013-09-18 19:21:11 +00:00
|
|
|
bottom_layer, top_layer,
|
2014-02-25 10:40:34 +00:00
|
|
|
via->GetNetCode() );
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
2008-11-27 10:12:46 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( (other == NULL) && (zone == NULL) )
|
|
|
|
flag_erase |= 0x20;
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2013-03-28 06:40:19 +00:00
|
|
|
track->SetState( BUSY, false );
|
2012-09-07 19:29:44 +00:00
|
|
|
}
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( flag_erase )
|
2011-09-07 19:41:04 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
// remove segment from board
|
|
|
|
track->DeleteStructure();
|
|
|
|
// iterate, because a track connected to the deleted track
|
|
|
|
// is now perhaps now not connected and should be deleted
|
|
|
|
item_erased = true;
|
|
|
|
modified = true;
|
2011-09-07 19:41:04 +00:00
|
|
|
}
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
2012-09-07 19:29:44 +00:00
|
|
|
|
|
|
|
return modified;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Delete null length segments, and intermediate points ..
|
2012-09-07 19:29:44 +00:00
|
|
|
bool TRACKS_CLEANER::clean_segments()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
bool modified = false;
|
2009-06-11 18:30:03 +00:00
|
|
|
TRACK* segment, * nextsegment;
|
2007-10-19 19:58:31 +00:00
|
|
|
TRACK* other;
|
2010-11-21 18:28:32 +00:00
|
|
|
int flag, no_inc;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
|
|
|
|
2010-11-21 18:28:32 +00:00
|
|
|
// Delete null segments
|
2012-09-07 19:29:44 +00:00
|
|
|
for( segment = m_Brd->m_Track; segment; segment = nextsegment )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2009-06-11 18:30:03 +00:00
|
|
|
nextsegment = segment->Next();
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( segment->IsNull() ) // Length segment = 0; delete it
|
|
|
|
segment->DeleteStructure();
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// Delete redundant segments, i.e. segments having the same end points
|
|
|
|
// and layers
|
|
|
|
for( segment = m_Brd->m_Track; segment; segment = segment->Next() )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2009-06-11 18:30:03 +00:00
|
|
|
for( other = segment->Next(); other; other = nextsegment )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2009-06-11 18:30:03 +00:00
|
|
|
nextsegment = other->Next();
|
2012-09-07 19:29:44 +00:00
|
|
|
bool erase = false;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2007-10-19 19:58:31 +00:00
|
|
|
if( segment->Type() != other->Type() )
|
2007-08-10 19:14:51 +00:00
|
|
|
continue;
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2007-10-19 19:58:31 +00:00
|
|
|
if( segment->GetLayer() != other->GetLayer() )
|
2007-08-10 19:14:51 +00:00
|
|
|
continue;
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2014-02-25 10:40:34 +00:00
|
|
|
if( segment->GetNetCode() != other->GetNetCode() )
|
2007-08-10 19:14:51 +00:00
|
|
|
break;
|
|
|
|
|
2013-01-13 00:04:00 +00:00
|
|
|
if( ( segment->GetStart() == other->GetStart() ) &&
|
|
|
|
( segment->GetEnd() == other->GetEnd() ) )
|
2012-09-07 19:29:44 +00:00
|
|
|
erase = true;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2013-01-13 00:04:00 +00:00
|
|
|
if( ( segment->GetStart() == other->GetEnd() ) &&
|
|
|
|
( segment->GetEnd() == other->GetStart() ) )
|
2012-09-07 19:29:44 +00:00
|
|
|
erase = true;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// Delete redundant point
|
2007-08-10 19:14:51 +00:00
|
|
|
if( erase )
|
|
|
|
{
|
2007-10-19 19:58:31 +00:00
|
|
|
other->DeleteStructure();
|
2012-09-07 19:29:44 +00:00
|
|
|
modified = true;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-11 07:33:17 +00:00
|
|
|
// merge collinear segments:
|
2012-09-07 19:29:44 +00:00
|
|
|
for( segment = m_Brd->m_Track; segment; segment = nextsegment )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2007-10-19 19:58:31 +00:00
|
|
|
TRACK* segStart;
|
|
|
|
TRACK* segEnd;
|
2007-10-19 23:02:11 +00:00
|
|
|
TRACK* segDelete;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2009-06-11 18:30:03 +00:00
|
|
|
nextsegment = segment->Next();
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2011-10-01 19:24:27 +00:00
|
|
|
if( segment->Type() != PCB_TRACE_T )
|
2007-08-10 19:14:51 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
flag = no_inc = 0;
|
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// search for a possible point connected to the START point of the current segment
|
2007-10-19 23:02:11 +00:00
|
|
|
for( segStart = segment->Next(); ; )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2012-07-25 18:46:25 +00:00
|
|
|
segStart = segment->GetTrace( segStart, NULL, FLG_START );
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2007-10-19 19:58:31 +00:00
|
|
|
if( segStart )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2007-10-19 19:58:31 +00:00
|
|
|
// the two segments must have the same width
|
2013-01-13 00:04:00 +00:00
|
|
|
if( segment->GetWidth() != segStart->GetWidth() )
|
2007-08-10 19:14:51 +00:00
|
|
|
break;
|
|
|
|
|
2007-10-19 19:58:31 +00:00
|
|
|
// it cannot be a via
|
2011-10-01 19:24:27 +00:00
|
|
|
if( segStart->Type() != PCB_TRACE_T )
|
2007-08-10 19:14:51 +00:00
|
|
|
break;
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// We must have only one segment connected
|
2013-03-28 06:40:19 +00:00
|
|
|
segStart->SetState( BUSY, true );
|
2012-09-07 19:29:44 +00:00
|
|
|
other = segment->GetTrace( m_Brd->m_Track, NULL, FLG_START );
|
2013-03-28 06:40:19 +00:00
|
|
|
segStart->SetState( BUSY, false );
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2007-10-19 19:58:31 +00:00
|
|
|
if( other == NULL )
|
2012-02-19 04:02:19 +00:00
|
|
|
flag = 1; // OK
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2007-08-10 19:14:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-09-15 17:58:35 +00:00
|
|
|
if( flag ) // We have the starting point of the segment is connected to an other segment
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2012-09-11 07:33:17 +00:00
|
|
|
segDelete = mergeCollinearSegmentIfPossible( segment, segStart, FLG_START );
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2007-10-19 23:02:11 +00:00
|
|
|
if( segDelete )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2010-11-21 18:28:32 +00:00
|
|
|
no_inc = 1;
|
2007-10-19 23:02:11 +00:00
|
|
|
segDelete->DeleteStructure();
|
2012-09-07 19:29:44 +00:00
|
|
|
modified = true;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
// search for a possible point connected to the END point of the current segment:
|
2007-10-19 23:02:11 +00:00
|
|
|
for( segEnd = segment->Next(); ; )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2012-07-25 18:46:25 +00:00
|
|
|
segEnd = segment->GetTrace( segEnd, NULL, FLG_END );
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2007-10-19 19:58:31 +00:00
|
|
|
if( segEnd )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2013-01-13 00:04:00 +00:00
|
|
|
if( segment->GetWidth() != segEnd->GetWidth() )
|
2007-08-10 19:14:51 +00:00
|
|
|
break;
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2011-10-01 19:24:27 +00:00
|
|
|
if( segEnd->Type() != PCB_TRACE_T )
|
2007-08-10 19:14:51 +00:00
|
|
|
break;
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
// We must have only one segment connected
|
2013-03-28 06:40:19 +00:00
|
|
|
segEnd->SetState( BUSY, true );
|
2012-09-07 19:29:44 +00:00
|
|
|
other = segment->GetTrace( m_Brd->m_Track, NULL, FLG_END );
|
2013-03-28 06:40:19 +00:00
|
|
|
segEnd->SetState( BUSY, false );
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2007-10-19 19:58:31 +00:00
|
|
|
if( other == NULL )
|
2012-02-19 04:02:19 +00:00
|
|
|
flag |= 2; // Ok
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2007-08-10 19:14:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
2011-09-07 19:41:04 +00:00
|
|
|
{
|
2007-08-10 19:14:51 +00:00
|
|
|
break;
|
2011-09-07 19:41:04 +00:00
|
|
|
}
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
|
2011-09-15 17:58:35 +00:00
|
|
|
if( flag & 2 ) // We have the ending point of the segment is connected to an other segment
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2012-09-11 07:33:17 +00:00
|
|
|
segDelete = mergeCollinearSegmentIfPossible( segment, segEnd, FLG_END );
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2007-10-19 23:02:11 +00:00
|
|
|
if( segDelete )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2007-10-19 19:58:31 +00:00
|
|
|
no_inc = 1;
|
2007-10-19 23:02:11 +00:00
|
|
|
segDelete->DeleteStructure();
|
2012-09-07 19:29:44 +00:00
|
|
|
modified = true;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
if( no_inc ) // The current segment was modified, retry to merge it
|
2009-06-11 18:30:03 +00:00
|
|
|
nextsegment = segment->Next();
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
return modified;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2012-02-19 04:02:19 +00:00
|
|
|
/** Function used by clean_segments.
|
2012-09-11 07:33:17 +00:00
|
|
|
* Test if aTrackRef and aCandidate (which must have a common end) are collinear.
|
2007-10-27 18:05:50 +00:00
|
|
|
* and see if the common point is not on a pad (i.e. if this common point can be removed).
|
2012-09-11 07:33:17 +00:00
|
|
|
* the ending point of aTrackRef is the start point (aEndType == START)
|
2011-11-15 19:21:16 +00:00
|
|
|
* or the end point (aEndType != START)
|
2012-09-07 19:29:44 +00:00
|
|
|
* flags START_ON_PAD and END_ON_PAD must be set before calling this function
|
2011-11-15 19:21:16 +00:00
|
|
|
* if the common point can be deleted, this function
|
|
|
|
* change the common point coordinate of the aTrackRef segm
|
2007-10-27 18:05:50 +00:00
|
|
|
* (and therefore connect the 2 other ending points)
|
2011-11-15 19:21:16 +00:00
|
|
|
* and return aCandidate (which can be deleted).
|
2007-10-27 18:05:50 +00:00
|
|
|
* else return NULL
|
2007-08-10 19:14:51 +00:00
|
|
|
*/
|
2012-09-11 07:33:17 +00:00
|
|
|
TRACK* TRACKS_CLEANER::mergeCollinearSegmentIfPossible( TRACK* aTrackRef, TRACK* aCandidate,
|
2011-12-12 14:02:37 +00:00
|
|
|
int aEndType )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2013-01-13 00:04:00 +00:00
|
|
|
if( aTrackRef->GetWidth() != aCandidate->GetWidth() )
|
2011-11-15 19:21:16 +00:00
|
|
|
return NULL;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2011-11-15 19:21:16 +00:00
|
|
|
bool is_colinear = false;
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2011-11-15 19:21:16 +00:00
|
|
|
// Trivial case: superimposed tracks ( tracks, not vias ):
|
|
|
|
if( aTrackRef->Type() == PCB_TRACE_T && aCandidate->Type() == PCB_TRACE_T )
|
|
|
|
{
|
2013-01-13 00:04:00 +00:00
|
|
|
if( ( aTrackRef->GetStart() == aCandidate->GetStart() ) &&
|
|
|
|
( aTrackRef->GetEnd() == aCandidate->GetEnd() ) )
|
2012-09-07 19:29:44 +00:00
|
|
|
return aCandidate;
|
2011-11-15 19:21:16 +00:00
|
|
|
|
2013-01-13 00:04:00 +00:00
|
|
|
if( ( aTrackRef->GetStart() == aCandidate->GetEnd() ) &&
|
|
|
|
( aTrackRef->GetEnd() == aCandidate->GetStart() ) )
|
2012-09-07 19:29:44 +00:00
|
|
|
return aCandidate;
|
2011-11-15 19:21:16 +00:00
|
|
|
}
|
|
|
|
|
2013-01-13 00:04:00 +00:00
|
|
|
int refdx = aTrackRef->GetEnd().x - aTrackRef->GetStart().x;
|
|
|
|
int refdy = aTrackRef->GetEnd().y - aTrackRef->GetStart().y;
|
2011-11-15 19:21:16 +00:00
|
|
|
|
2013-01-13 00:04:00 +00:00
|
|
|
int segmdx = aCandidate->GetEnd().x - aCandidate->GetStart().x;
|
|
|
|
int segmdy = aCandidate->GetEnd().y - aCandidate->GetStart().y;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2007-10-27 18:05:50 +00:00
|
|
|
// test for vertical alignment (easy to handle)
|
2007-08-10 19:14:51 +00:00
|
|
|
if( refdx == 0 )
|
|
|
|
{
|
|
|
|
if( segmdx != 0 )
|
|
|
|
return NULL;
|
|
|
|
else
|
2011-11-15 19:21:16 +00:00
|
|
|
is_colinear = true;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2007-10-27 18:05:50 +00:00
|
|
|
// test for horizontal alignment (easy to handle)
|
2007-08-10 19:14:51 +00:00
|
|
|
if( refdy == 0 )
|
|
|
|
{
|
|
|
|
if( segmdy != 0 )
|
|
|
|
return NULL;
|
|
|
|
else
|
2011-11-15 19:21:16 +00:00
|
|
|
is_colinear = true;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
|
2011-09-15 17:58:35 +00:00
|
|
|
/* test if alignment in other cases
|
2011-11-24 19:57:41 +00:00
|
|
|
* We must have refdy/refdx == segmdy/segmdx, (i.e. same slope)
|
|
|
|
* or refdy * segmdx == segmdy * refdx
|
|
|
|
*/
|
2011-11-15 19:21:16 +00:00
|
|
|
if( is_colinear == false )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2011-11-24 19:57:41 +00:00
|
|
|
if( ( double)refdy * segmdx != (double)refdx * segmdy )
|
2007-08-10 19:14:51 +00:00
|
|
|
return NULL;
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2011-11-15 19:21:16 +00:00
|
|
|
is_colinear = true;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
|
2007-10-27 18:05:50 +00:00
|
|
|
/* Here we have 2 aligned segments:
|
2011-09-15 17:58:35 +00:00
|
|
|
* We must change the pt_ref common point only if not on a pad
|
|
|
|
* (this function) is called when there is only 2 connected segments,
|
|
|
|
*and if this point is not on a pad, it can be removed and the 2 segments will be merged
|
|
|
|
*/
|
2012-07-25 18:46:25 +00:00
|
|
|
if( aEndType == FLG_START )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
// We do not have a pad, which is a always terminal point for a track
|
|
|
|
if( aTrackRef->GetState( START_ON_PAD) )
|
2007-08-10 19:14:51 +00:00
|
|
|
return NULL;
|
|
|
|
|
2011-09-15 17:58:35 +00:00
|
|
|
/* change the common point coordinate of pt_segm to use the other point
|
|
|
|
* of pt_segm (pt_segm will be removed later) */
|
2013-01-13 00:04:00 +00:00
|
|
|
if( aTrackRef->GetStart() == aCandidate->GetStart() )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2013-01-13 00:04:00 +00:00
|
|
|
aTrackRef->SetStart( aCandidate->GetEnd());
|
2012-09-07 19:29:44 +00:00
|
|
|
aTrackRef->start = aCandidate->end;
|
|
|
|
aTrackRef->SetState( START_ON_PAD, aCandidate->GetState( END_ON_PAD) );
|
2011-11-15 19:21:16 +00:00
|
|
|
return aCandidate;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
2007-10-27 18:05:50 +00:00
|
|
|
else
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2013-01-13 00:04:00 +00:00
|
|
|
aTrackRef->SetStart( aCandidate->GetStart() );
|
2012-09-07 19:29:44 +00:00
|
|
|
aTrackRef->start = aCandidate->start;
|
|
|
|
aTrackRef->SetState( START_ON_PAD, aCandidate->GetState( START_ON_PAD) );
|
2011-11-15 19:21:16 +00:00
|
|
|
return aCandidate;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
2011-11-15 19:21:16 +00:00
|
|
|
else // aEndType == END
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2012-09-07 19:29:44 +00:00
|
|
|
// We do not have a pad, which is a always terminal point for a track
|
|
|
|
if( aTrackRef->GetState( END_ON_PAD) )
|
2007-08-10 19:14:51 +00:00
|
|
|
return NULL;
|
|
|
|
|
2011-09-15 17:58:35 +00:00
|
|
|
/* change the common point coordinate of pt_segm to use the other point
|
|
|
|
* of pt_segm (pt_segm will be removed later) */
|
2013-01-13 00:04:00 +00:00
|
|
|
if( aTrackRef->GetEnd() == aCandidate->GetStart() )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2013-01-13 00:04:00 +00:00
|
|
|
aTrackRef->SetEnd( aCandidate->GetEnd() );
|
2012-09-07 19:29:44 +00:00
|
|
|
aTrackRef->end = aCandidate->end;
|
|
|
|
aTrackRef->SetState( END_ON_PAD, aCandidate->GetState( END_ON_PAD) );
|
2011-11-15 19:21:16 +00:00
|
|
|
return aCandidate;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
2007-10-27 18:05:50 +00:00
|
|
|
else
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2013-01-13 00:04:00 +00:00
|
|
|
aTrackRef->SetEnd( aCandidate->GetStart() );
|
2012-09-07 19:29:44 +00:00
|
|
|
aTrackRef->end = aCandidate->start;
|
|
|
|
aTrackRef->SetState( END_ON_PAD, aCandidate->GetState( START_ON_PAD) );
|
2011-11-15 19:21:16 +00:00
|
|
|
return aCandidate;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2007-08-10 19:14:51 +00:00
|
|
|
return NULL;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-26 09:37:36 +00:00
|
|
|
bool PCB_EDIT_FRAME::RemoveMisConnectedTracks()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-01-26 09:37:36 +00:00
|
|
|
/* finds all track segments which are mis-connected (to more than one net).
|
|
|
|
* When such a bad segment is found, it is flagged to be removed.
|
|
|
|
* All tracks having at least one flagged segment are removed.
|
|
|
|
*/
|
2007-10-15 03:26:38 +00:00
|
|
|
TRACK* segment;
|
|
|
|
TRACK* other;
|
|
|
|
TRACK* next;
|
2007-08-10 19:14:51 +00:00
|
|
|
int net_code_s, net_code_e;
|
2010-11-21 18:28:32 +00:00
|
|
|
bool isModified = false;
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2010-04-16 16:28:35 +00:00
|
|
|
for( segment = GetBoard()->m_Track; segment; segment = (TRACK*) segment->Next() )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2013-03-28 06:40:19 +00:00
|
|
|
segment->SetState( FLAG0, false );
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2007-10-15 03:26:38 +00:00
|
|
|
// find the netcode for segment using anything connected to the "start" of "segment"
|
2007-08-10 19:14:51 +00:00
|
|
|
net_code_s = -1;
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( segment->start && segment->start->Type()==PCB_PAD_T )
|
2007-10-15 03:26:38 +00:00
|
|
|
{
|
|
|
|
// get the netcode of the pad to propagate.
|
2014-02-25 10:40:34 +00:00
|
|
|
net_code_s = ((D_PAD*)(segment->start))->GetNetCode();
|
2007-10-15 03:26:38 +00:00
|
|
|
}
|
2007-08-10 19:14:51 +00:00
|
|
|
else
|
|
|
|
{
|
2012-07-25 18:46:25 +00:00
|
|
|
other = segment->GetTrace( GetBoard()->m_Track, NULL, FLG_START );
|
2011-09-16 14:13:02 +00:00
|
|
|
|
2007-10-15 03:26:38 +00:00
|
|
|
if( other )
|
2014-02-25 10:40:34 +00:00
|
|
|
net_code_s = other->GetNetCode();
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2007-08-10 19:14:51 +00:00
|
|
|
if( net_code_s < 0 )
|
2007-10-15 03:26:38 +00:00
|
|
|
continue; // the "start" of segment is not connected
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2007-10-15 03:26:38 +00:00
|
|
|
// find the netcode for segment using anything connected to the "end" of "segment"
|
2007-08-10 19:14:51 +00:00
|
|
|
net_code_e = -1;
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2012-09-07 19:29:44 +00:00
|
|
|
if( segment->end && segment->end->Type()==PCB_PAD_T )
|
2007-10-15 03:26:38 +00:00
|
|
|
{
|
2014-02-25 10:40:34 +00:00
|
|
|
net_code_e = ((D_PAD*)(segment->end))->GetNetCode();
|
2007-10-15 03:26:38 +00:00
|
|
|
}
|
2007-08-10 19:14:51 +00:00
|
|
|
else
|
|
|
|
{
|
2012-07-25 18:46:25 +00:00
|
|
|
other = segment->GetTrace( GetBoard()->m_Track, NULL, FLG_END );
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2007-10-15 03:26:38 +00:00
|
|
|
if( other )
|
2014-02-25 10:40:34 +00:00
|
|
|
net_code_e = other->GetNetCode();
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( net_code_e < 0 )
|
2007-10-15 03:26:38 +00:00
|
|
|
continue; // the "end" of segment is not connected
|
2007-08-10 19:14:51 +00:00
|
|
|
|
2012-01-26 09:37:36 +00:00
|
|
|
// Netcodes do not agree, so mark the segment as "to be removed"
|
2007-08-10 19:14:51 +00:00
|
|
|
if( net_code_s != net_code_e )
|
|
|
|
{
|
2013-03-28 06:40:19 +00:00
|
|
|
segment->SetState( FLAG0, true );
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-26 09:37:36 +00:00
|
|
|
// Remove tracks having a flagged segment
|
2012-09-07 19:29:44 +00:00
|
|
|
for( segment = GetBoard()->m_Track; segment; segment = next )
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2007-10-15 03:26:38 +00:00
|
|
|
next = (TRACK*) segment->Next();
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2011-09-15 17:58:35 +00:00
|
|
|
if( segment->GetState( FLAG0 ) ) // Segment is flagged to be removed
|
2007-08-10 19:14:51 +00:00
|
|
|
{
|
2013-03-28 06:40:19 +00:00
|
|
|
segment->SetState( FLAG0, false );
|
2010-11-21 18:28:32 +00:00
|
|
|
isModified = true;
|
2010-04-16 16:28:35 +00:00
|
|
|
GetBoard()->m_Status_Pcb = 0;
|
2012-01-26 09:37:36 +00:00
|
|
|
Remove_One_Track( NULL, segment );
|
2011-09-15 17:58:35 +00:00
|
|
|
|
2012-01-26 09:37:36 +00:00
|
|
|
// the current segment is deleted,
|
|
|
|
// we do not know the next "not yet tested" segment,
|
|
|
|
// so restart to the beginning
|
2010-11-21 18:28:32 +00:00
|
|
|
next = GetBoard()->m_Track;
|
2007-08-10 19:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-21 18:28:32 +00:00
|
|
|
return isModified;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|