258 lines
6.9 KiB
C++
258 lines
6.9 KiB
C++
/*********************************/
|
|
/* Module de nettoyage du schema */
|
|
/*********************************/
|
|
|
|
#include "fctsys.h"
|
|
#include "gr_basic.h"
|
|
|
|
#include "common.h"
|
|
#include "program.h"
|
|
#include "libcmp.h"
|
|
#include "general.h"
|
|
#include "netlist.h"
|
|
#include "macros.h"
|
|
#include "protos.h"
|
|
|
|
|
|
/* Routines locales */
|
|
static int TstAlignSegment(EDA_DrawLineStruct* RefSegm, EDA_DrawLineStruct* TstSegm);
|
|
|
|
/* Variable locales */
|
|
|
|
|
|
/*******************************************/
|
|
bool SCH_SCREEN::SchematicCleanUp(wxDC * DC)
|
|
/*******************************************/
|
|
/* Routine de nettoyage:
|
|
- regroupe les segments de fils (ou de bus) alignes en 1 seul segment
|
|
- Detecte les objets identiques superposes
|
|
*/
|
|
{
|
|
EDA_BaseStruct *DrawList, * TstDrawList;
|
|
int flag;
|
|
bool Modify = FALSE;
|
|
|
|
DrawList = EEDrawList;
|
|
for ( ;DrawList != NULL; DrawList = DrawList->Pnext )
|
|
{
|
|
if( DrawList->m_StructType == DRAW_SEGMENT_STRUCT_TYPE )
|
|
{
|
|
TstDrawList = DrawList->Pnext;
|
|
while ( TstDrawList )
|
|
{
|
|
if( TstDrawList->m_StructType == DRAW_SEGMENT_STRUCT_TYPE )
|
|
{
|
|
flag = TstAlignSegment( (EDA_DrawLineStruct*)DrawList,
|
|
(EDA_DrawLineStruct*)TstDrawList);
|
|
if (flag ) /* Suppression de TstSegm */
|
|
{
|
|
/* keep the bits set in .m_Flags, because the deleted segment can be flagged */
|
|
DrawList->m_Flags |= TstDrawList->m_Flags;
|
|
EraseStruct(TstDrawList, this);
|
|
SetRefreshReq();
|
|
TstDrawList = EEDrawList;
|
|
Modify = TRUE;
|
|
}
|
|
else TstDrawList = TstDrawList->Pnext;
|
|
}
|
|
else TstDrawList = TstDrawList->Pnext;
|
|
}
|
|
}
|
|
}
|
|
EDA_Appl->SchematicFrame->TestDanglingEnds(EEDrawList, DC);
|
|
return Modify;
|
|
}
|
|
|
|
|
|
/***********************************************/
|
|
void BreakSegmentOnJunction( SCH_SCREEN * Screen )
|
|
/************************************************/
|
|
/* Routine creant des debuts / fin de segment (BUS ou WIRES) sur les jonctions
|
|
et les raccords
|
|
*/
|
|
{
|
|
EDA_BaseStruct *DrawList;
|
|
|
|
if( Screen == NULL )
|
|
{
|
|
DisplayError(NULL, wxT("BreakSegmentOnJunction() error: NULL screen"));
|
|
return;
|
|
}
|
|
|
|
DrawList = Screen->EEDrawList;
|
|
while ( DrawList )
|
|
{
|
|
switch( DrawList->m_StructType )
|
|
{
|
|
case DRAW_JUNCTION_STRUCT_TYPE :
|
|
#undef STRUCT
|
|
#define STRUCT ((DrawJunctionStruct*)DrawList)
|
|
BreakSegment(Screen, STRUCT->m_Pos);
|
|
break;
|
|
|
|
case DRAW_BUSENTRY_STRUCT_TYPE :
|
|
#undef STRUCT
|
|
#define STRUCT ((DrawBusEntryStruct*)DrawList)
|
|
BreakSegment(Screen, STRUCT->m_Pos);
|
|
BreakSegment(Screen, STRUCT->m_End());
|
|
break;
|
|
|
|
case DRAW_SEGMENT_STRUCT_TYPE :
|
|
case DRAW_NOCONNECT_STRUCT_TYPE :
|
|
case DRAW_LABEL_STRUCT_TYPE :
|
|
case DRAW_GLOBAL_LABEL_STRUCT_TYPE :
|
|
case DRAW_LIB_ITEM_STRUCT_TYPE :
|
|
case DRAW_PICK_ITEM_STRUCT_TYPE :
|
|
case DRAW_POLYLINE_STRUCT_TYPE :
|
|
case DRAW_MARKER_STRUCT_TYPE :
|
|
case DRAW_TEXT_STRUCT_TYPE :
|
|
case DRAW_SHEET_STRUCT_TYPE :
|
|
case DRAW_SHEETLABEL_STRUCT_TYPE :
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
DrawList = DrawList->Pnext;
|
|
}
|
|
}
|
|
|
|
|
|
/*********************************************************/
|
|
DrawPickedStruct * BreakSegment(SCH_SCREEN * screen,
|
|
wxPoint breakpoint, bool PutInUndoList)
|
|
/*********************************************************/
|
|
/* Coupe un segment ( BUS, WIRE ) en 2 au point breakpoint,
|
|
- si ce point est sur le segment
|
|
- extremites non comprises
|
|
If PutInUndoList == TRUE, create a list of modifictions, for undo command
|
|
*/
|
|
{
|
|
EDA_BaseStruct *DrawList;
|
|
EDA_DrawLineStruct * segment, * NewSegment;
|
|
int ox, oy, fx, fy;
|
|
DrawPickedStruct * List = NULL;
|
|
|
|
DrawList = screen->EEDrawList;
|
|
while ( DrawList )
|
|
{
|
|
switch( DrawList->m_StructType )
|
|
{
|
|
case DRAW_SEGMENT_STRUCT_TYPE :
|
|
segment = (EDA_DrawLineStruct*)DrawList;
|
|
ox = segment->m_Start.x; oy = segment->m_Start.y;
|
|
fx = segment->m_End.x; fy = segment->m_End.y;
|
|
if( distance( fx - ox, fy - oy, breakpoint.x - ox, breakpoint.y - oy, 0 ) == 0 )
|
|
break;
|
|
/* Segment connecte: doit etre coupe en 2 si px,py n'est
|
|
pas une extremite */
|
|
if( (ox == breakpoint.x) && (oy == breakpoint.y ) ) break;
|
|
if( (fx == breakpoint.x) && (fy == breakpoint.y ) ) break;
|
|
/* Ici il faut couper le segment en 2 */
|
|
if ( PutInUndoList ) // First: put copy of the old segment in undo list
|
|
{
|
|
DrawPickedStruct * wrapper = new DrawPickedStruct();
|
|
wrapper->m_Flags = IS_CHANGED;
|
|
wrapper->m_PickedStruct = segment->GenCopy();
|
|
wrapper->m_Image = segment;
|
|
wrapper->m_PickedStruct->m_Image = segment;
|
|
wrapper->Pnext = List;
|
|
List = wrapper;
|
|
}
|
|
NewSegment = segment->GenCopy();
|
|
NewSegment->m_Start = breakpoint;
|
|
segment->m_End = NewSegment->m_Start;
|
|
NewSegment->Pnext = segment->Pnext;
|
|
segment->Pnext = NewSegment;
|
|
DrawList = NewSegment;
|
|
if ( PutInUndoList )
|
|
{
|
|
DrawPickedStruct * wrapper = new DrawPickedStruct();
|
|
wrapper->m_Flags = IS_NEW;
|
|
wrapper->m_Image = NewSegment;
|
|
wrapper->Pnext = List;
|
|
List = wrapper;
|
|
}
|
|
break;
|
|
|
|
case DRAW_JUNCTION_STRUCT_TYPE :
|
|
case DRAW_BUSENTRY_STRUCT_TYPE :
|
|
case DRAW_POLYLINE_STRUCT_TYPE :
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
DrawList = DrawList->Pnext;
|
|
}
|
|
|
|
return List;
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************/
|
|
static int TstAlignSegment( EDA_DrawLineStruct* RefSegm,
|
|
EDA_DrawLineStruct* TstSegm)
|
|
/***********************************************************/
|
|
|
|
/* Search if the 2 segments RefSegm and TstSegm are on a line.
|
|
Retourn 0 if no
|
|
1 if yes, and RefSegm is modified to be the equivalent segment
|
|
*/
|
|
{
|
|
if( RefSegm == TstSegm ) return(0);
|
|
if( RefSegm->m_Layer != TstSegm->m_Layer ) return(0);
|
|
|
|
// search for a common end, and modify coordinates to ensure RefSegm->m_End == TstSegm->m_Start
|
|
if ( RefSegm->m_Start == TstSegm->m_Start )
|
|
{
|
|
if ( RefSegm->m_End == TstSegm->m_End ) // trivial case: RefSegm and TstSegm are identical
|
|
return 1;
|
|
EXCHG(RefSegm->m_Start, RefSegm->m_End); // at this point, RefSegm->m_End == TstSegm->m_Start
|
|
}
|
|
else if ( RefSegm->m_Start == TstSegm->m_End )
|
|
{
|
|
EXCHG(RefSegm->m_Start, RefSegm->m_End);
|
|
EXCHG(TstSegm->m_Start, TstSegm->m_End); // at this point, RefSegm->m_End == TstSegm->m_Start
|
|
}
|
|
else if ( RefSegm->m_End == TstSegm->m_End )
|
|
{
|
|
EXCHG(TstSegm->m_Start, TstSegm->m_End); // at this point, RefSegm->m_End == TstSegm->m_Start
|
|
}
|
|
else if ( RefSegm->m_End != TstSegm->m_Start ) // No common end point, segments cannot be merged
|
|
return 0;
|
|
|
|
/* Test alignment: */
|
|
if ( RefSegm->m_Start.y == RefSegm->m_End.y ) // Horizontal segment
|
|
{
|
|
if ( TstSegm->m_Start.y == TstSegm->m_End.y )
|
|
{
|
|
RefSegm->m_End = TstSegm->m_End;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
else if ( RefSegm->m_Start.x == RefSegm->m_End.x ) // Vertical segment
|
|
{
|
|
if ( TstSegm->m_Start.x == TstSegm->m_End.x )
|
|
{
|
|
RefSegm->m_End = TstSegm->m_End;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
if (atan2(RefSegm->m_Start.x - RefSegm->m_End.x, RefSegm->m_Start.y - RefSegm->m_End.y) ==
|
|
atan2(TstSegm->m_Start.x - TstSegm->m_End.x, TstSegm->m_Start.y - TstSegm->m_End.y) )
|
|
{
|
|
RefSegm->m_End = TstSegm->m_End;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|