2007-06-05 12:10:51 +00:00
|
|
|
|
/*********************/
|
|
|
|
|
/* dangling_ends.cpp */
|
|
|
|
|
/*********************/
|
|
|
|
|
|
|
|
|
|
#include "fctsys.h"
|
|
|
|
|
#include "gr_basic.h"
|
|
|
|
|
#include "common.h"
|
|
|
|
|
#include "program.h"
|
|
|
|
|
#include "libcmp.h"
|
|
|
|
|
#include "general.h"
|
|
|
|
|
|
|
|
|
|
#include "netlist.h" /* Definitions generales liees au calcul de netliste */
|
|
|
|
|
#include "protos.h"
|
|
|
|
|
|
|
|
|
|
enum End_Type
|
|
|
|
|
{
|
|
|
|
|
UNKNOWN = 0,
|
|
|
|
|
WIRE_START_END,
|
|
|
|
|
WIRE_END_END,
|
|
|
|
|
BUS_START_END,
|
|
|
|
|
BUS_END_END,
|
|
|
|
|
JUNCTION_END,
|
|
|
|
|
PIN_END,
|
|
|
|
|
LABEL_END,
|
|
|
|
|
ENTRY_END,
|
|
|
|
|
SHEET_LABEL_END
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class DanglingEndHandle
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
const void * m_Item;
|
|
|
|
|
wxPoint m_Pos;
|
|
|
|
|
int m_Type;
|
|
|
|
|
DanglingEndHandle * m_Pnext;
|
|
|
|
|
|
|
|
|
|
DanglingEndHandle(int type)
|
|
|
|
|
{
|
|
|
|
|
m_Item = NULL;
|
|
|
|
|
m_Type = type;
|
|
|
|
|
m_Pnext = NULL;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
DanglingEndHandle * ItemList;
|
|
|
|
|
|
|
|
|
|
static void TestWireForDangling(EDA_DrawLineStruct * DrawRef,
|
|
|
|
|
WinEDA_SchematicFrame * frame, wxDC * DC);
|
|
|
|
|
void TestLabelForDangling(DrawTextStruct * label,
|
|
|
|
|
WinEDA_SchematicFrame * frame, wxDC * DC);
|
|
|
|
|
DanglingEndHandle * RebuildEndList(EDA_BaseStruct *DrawList);
|
|
|
|
|
|
|
|
|
|
/**********************************************************/
|
|
|
|
|
bool SegmentIntersect(int Sx1, int Sy1, int Sx2, int Sy2,
|
|
|
|
|
int Px1, int Py1)
|
|
|
|
|
/**********************************************************/
|
|
|
|
|
/* Retourne TRUE si le point P est sur le segment S.
|
|
|
|
|
Le segment est suppose horizontal ou vertical.
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
int Sxmin, Sxmax, Symin, Symax;
|
|
|
|
|
|
|
|
|
|
if (Sx1 == Sx2) /* Line S is vertical. */
|
|
|
|
|
{
|
|
|
|
|
Symin = MIN(Sy1, Sy2); Symax = MAX(Sy1, Sy2);
|
|
|
|
|
if (Px1 != Sx1) return FALSE;
|
|
|
|
|
if (Py1 >= Symin && Py1 <= Symax) return TRUE;
|
|
|
|
|
else return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (Sy1 == Sy2) /* Line S is horizontal. */
|
|
|
|
|
{
|
|
|
|
|
Sxmin = MIN(Sx1, Sx2); Sxmax = MAX(Sx1, Sx2);
|
|
|
|
|
if (Py1 != Sy1) return FALSE;
|
|
|
|
|
if (Px1 >= Sxmin && Px1 <= Sxmax) return TRUE;
|
|
|
|
|
else return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else return FALSE; // Segments quelconques
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
void WinEDA_SchematicFrame::TestDanglingEnds(EDA_BaseStruct *DrawList, wxDC *DC)
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Met a jour les membres m_Dangling des wires, bus, labels
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
EDA_BaseStruct * DrawItem;
|
|
|
|
|
const DanglingEndHandle * DanglingItem, * nextitem;
|
|
|
|
|
|
|
|
|
|
if ( ItemList )
|
|
|
|
|
for ( DanglingItem = ItemList; DanglingItem != NULL; DanglingItem = nextitem)
|
|
|
|
|
{
|
|
|
|
|
nextitem = DanglingItem->m_Pnext;
|
|
|
|
|
delete DanglingItem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ItemList = RebuildEndList(DrawList);
|
|
|
|
|
// Controle des elements
|
|
|
|
|
for ( DrawItem = DrawList; DrawItem != NULL; DrawItem= DrawItem->Pnext)
|
|
|
|
|
{
|
|
|
|
|
switch( DrawItem->m_StructType )
|
|
|
|
|
{
|
|
|
|
|
case DRAW_GLOBAL_LABEL_STRUCT_TYPE:
|
|
|
|
|
case DRAW_LABEL_STRUCT_TYPE:
|
|
|
|
|
#undef STRUCT
|
|
|
|
|
#define STRUCT ((DrawLabelStruct*)DrawItem)
|
|
|
|
|
TestLabelForDangling(STRUCT, this, DC);
|
|
|
|
|
break;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DRAW_SEGMENT_STRUCT_TYPE:
|
|
|
|
|
#undef STRUCT
|
|
|
|
|
#define STRUCT ((EDA_DrawLineStruct*)DrawItem)
|
|
|
|
|
if( STRUCT->m_Layer == LAYER_WIRE)
|
|
|
|
|
{
|
|
|
|
|
TestWireForDangling(STRUCT, this, DC);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if( STRUCT->m_Layer == LAYER_NOTES) break;
|
|
|
|
|
if( STRUCT->m_Layer == LAYER_BUS)
|
|
|
|
|
{
|
|
|
|
|
STRUCT->m_StartIsDangling =
|
|
|
|
|
STRUCT->m_EndIsDangling = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/********************************************************************/
|
|
|
|
|
LibDrawPin * WinEDA_SchematicFrame::LocatePinEnd(EDA_BaseStruct *DrawList,
|
|
|
|
|
const wxPoint & pos)
|
|
|
|
|
/********************************************************************/
|
|
|
|
|
/* Teste si le point de coordonn<6E>es pos est sur l'extr<74>mit<69> d'une PIN
|
|
|
|
|
retourne un pointeur sur la pin
|
|
|
|
|
NULL sinon
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
EDA_SchComponentStruct * DrawLibItem;
|
|
|
|
|
LibDrawPin * Pin;
|
|
|
|
|
wxPoint pinpos;
|
|
|
|
|
|
|
|
|
|
Pin = LocateAnyPin(DrawList,pos, &DrawLibItem);
|
|
|
|
|
if( ! Pin ) return NULL;
|
|
|
|
|
|
|
|
|
|
pinpos = Pin->m_Pos;
|
|
|
|
|
|
|
|
|
|
if(DrawLibItem == NULL ) pinpos.y = -pinpos.y;
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int x1 = pinpos.x, y1 = pinpos.y;
|
|
|
|
|
pinpos.x = DrawLibItem->m_Pos.x + DrawLibItem->m_Transform[0][0] * x1
|
|
|
|
|
+ DrawLibItem->m_Transform[0][1] * y1;
|
|
|
|
|
pinpos.y = DrawLibItem->m_Pos.y + DrawLibItem->m_Transform[1][0] * x1
|
|
|
|
|
+ DrawLibItem->m_Transform[1][1] * y1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( (pos.x == pinpos.x) && (pos.y == pinpos.y) ) return Pin;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
|
void TestWireForDangling(EDA_DrawLineStruct * DrawRef,
|
|
|
|
|
WinEDA_SchematicFrame * frame, wxDC * DC)
|
|
|
|
|
/****************************************************************************/
|
|
|
|
|
{
|
|
|
|
|
DanglingEndHandle * terminal_item;
|
|
|
|
|
bool Sdangstate = TRUE, Edangstate = TRUE;
|
|
|
|
|
|
|
|
|
|
for ( terminal_item = ItemList; terminal_item != NULL;
|
|
|
|
|
terminal_item = terminal_item->m_Pnext)
|
|
|
|
|
{
|
|
|
|
|
if ( terminal_item->m_Item == DrawRef ) continue;
|
|
|
|
|
|
|
|
|
|
if ( (DrawRef->m_Start.x == terminal_item->m_Pos.x) &&
|
|
|
|
|
(DrawRef->m_Start.y == terminal_item->m_Pos.y) )
|
|
|
|
|
Sdangstate = FALSE;
|
|
|
|
|
|
|
|
|
|
if ( (DrawRef->m_End.x == terminal_item->m_Pos.x) &&
|
|
|
|
|
(DrawRef->m_End.y == terminal_item->m_Pos.y) )
|
|
|
|
|
Edangstate = FALSE;
|
|
|
|
|
|
|
|
|
|
if ( (Sdangstate == FALSE) && (Edangstate == FALSE) )
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (Sdangstate != DrawRef->m_StartIsDangling) ||
|
|
|
|
|
(Edangstate != DrawRef->m_EndIsDangling) )
|
|
|
|
|
{
|
|
|
|
|
if ( DC )
|
|
|
|
|
RedrawOneStruct(frame->DrawPanel,DC, DrawRef, g_XorMode);
|
|
|
|
|
DrawRef->m_StartIsDangling = Sdangstate;
|
|
|
|
|
DrawRef->m_EndIsDangling = Edangstate;
|
|
|
|
|
if ( DC )
|
|
|
|
|
RedrawOneStruct(frame->DrawPanel,DC, DrawRef, GR_DEFAULT_DRAWMODE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/********************************************************/
|
|
|
|
|
void TestLabelForDangling(DrawTextStruct * label,
|
|
|
|
|
WinEDA_SchematicFrame * frame, wxDC * DC)
|
|
|
|
|
/********************************************************/
|
|
|
|
|
{
|
|
|
|
|
DanglingEndHandle * terminal_item;
|
|
|
|
|
bool dangstate = TRUE;
|
|
|
|
|
|
|
|
|
|
for ( terminal_item = ItemList; terminal_item != NULL;
|
|
|
|
|
terminal_item = terminal_item->m_Pnext)
|
|
|
|
|
{
|
|
|
|
|
if ( terminal_item->m_Item == label ) continue;
|
|
|
|
|
switch( terminal_item->m_Type )
|
|
|
|
|
{
|
|
|
|
|
case PIN_END:
|
|
|
|
|
case LABEL_END:
|
|
|
|
|
case SHEET_LABEL_END:
|
|
|
|
|
if ( (label->m_Pos.x == terminal_item->m_Pos.x) &&
|
|
|
|
|
(label->m_Pos.y == terminal_item->m_Pos.y) )
|
|
|
|
|
dangstate = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case WIRE_START_END:
|
|
|
|
|
case BUS_START_END:
|
|
|
|
|
dangstate = ! SegmentIntersect(terminal_item->m_Pos.x,
|
|
|
|
|
terminal_item->m_Pos.y,
|
|
|
|
|
terminal_item->m_Pnext->m_Pos.x,
|
|
|
|
|
terminal_item->m_Pnext->m_Pos.y,
|
|
|
|
|
label->m_Pos.x, label->m_Pos.y);
|
|
|
|
|
terminal_item = terminal_item->m_Pnext;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case UNKNOWN:
|
|
|
|
|
case JUNCTION_END:
|
|
|
|
|
case ENTRY_END:
|
|
|
|
|
case WIRE_END_END:
|
|
|
|
|
case BUS_END_END:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dangstate == FALSE) break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( dangstate != label->m_IsDangling )
|
|
|
|
|
{
|
|
|
|
|
if ( DC )
|
|
|
|
|
RedrawOneStruct(frame->DrawPanel,DC, label, g_XorMode);
|
|
|
|
|
label->m_IsDangling = dangstate;
|
|
|
|
|
if ( DC )
|
|
|
|
|
RedrawOneStruct(frame->DrawPanel,DC, label, GR_DEFAULT_DRAWMODE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************/
|
|
|
|
|
wxPoint ReturnPinPhysicalPosition( LibDrawPin * Pin,
|
|
|
|
|
EDA_SchComponentStruct * DrawLibItem)
|
|
|
|
|
/****************************************************/
|
|
|
|
|
/* Retourne la position physique de la pin, qui d<>pend de l'orientation
|
|
|
|
|
du composant */
|
|
|
|
|
{
|
|
|
|
|
wxPoint PinPos = Pin->m_Pos;
|
|
|
|
|
|
|
|
|
|
if(DrawLibItem == NULL ) PinPos.y = -PinPos.y;
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int x = Pin->m_Pos.x, y = Pin->m_Pos.y;
|
|
|
|
|
PinPos.x = DrawLibItem->m_Pos.x + DrawLibItem->m_Transform[0][0] * x
|
|
|
|
|
+ DrawLibItem->m_Transform[0][1] * y;
|
|
|
|
|
PinPos.y = DrawLibItem->m_Pos.y + DrawLibItem->m_Transform[1][0] * x
|
|
|
|
|
+ DrawLibItem->m_Transform[1][1] * y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return PinPos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************/
|
|
|
|
|
DanglingEndHandle * RebuildEndList(EDA_BaseStruct *DrawList)
|
|
|
|
|
/***********************************************************/
|
|
|
|
|
{
|
|
|
|
|
DanglingEndHandle * StartList = NULL, *item, *lastitem = NULL;
|
|
|
|
|
EDA_BaseStruct * DrawItem;
|
|
|
|
|
|
|
|
|
|
for ( DrawItem = DrawList; DrawItem != NULL; DrawItem = DrawItem->Pnext)
|
|
|
|
|
{
|
|
|
|
|
switch( DrawItem->m_StructType )
|
|
|
|
|
{
|
|
|
|
|
case DRAW_LABEL_STRUCT_TYPE:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DRAW_GLOBAL_LABEL_STRUCT_TYPE:
|
|
|
|
|
#undef STRUCT
|
|
|
|
|
#define STRUCT ((DrawGlobalLabelStruct*)DrawItem)
|
|
|
|
|
item = new DanglingEndHandle(LABEL_END);
|
|
|
|
|
item->m_Item = DrawItem;
|
|
|
|
|
item->m_Pos = STRUCT->m_Pos;
|
|
|
|
|
if ( lastitem ) lastitem->m_Pnext = item;
|
|
|
|
|
else StartList = item;
|
|
|
|
|
lastitem = item;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DRAW_SEGMENT_STRUCT_TYPE:
|
|
|
|
|
#undef STRUCT
|
|
|
|
|
#define STRUCT ((EDA_DrawLineStruct*)DrawItem)
|
|
|
|
|
if( STRUCT->m_Layer == LAYER_NOTES ) break;
|
|
|
|
|
if( (STRUCT->m_Layer == LAYER_BUS) || (STRUCT->m_Layer == LAYER_WIRE) )
|
|
|
|
|
{
|
|
|
|
|
item = new DanglingEndHandle((STRUCT->m_Layer == LAYER_BUS) ?
|
|
|
|
|
BUS_START_END : WIRE_START_END);
|
|
|
|
|
item->m_Item = DrawItem;
|
|
|
|
|
item->m_Pos = STRUCT->m_Start;
|
|
|
|
|
if ( lastitem ) lastitem->m_Pnext = item;
|
|
|
|
|
else StartList = item;
|
|
|
|
|
lastitem = item;
|
|
|
|
|
item = new DanglingEndHandle((STRUCT->m_Layer == LAYER_BUS) ?
|
|
|
|
|
BUS_END_END : WIRE_END_END);
|
|
|
|
|
item->m_Item = DrawItem;
|
|
|
|
|
item->m_Pos = STRUCT->m_End;
|
|
|
|
|
lastitem->m_Pnext = item;
|
|
|
|
|
lastitem = item;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DRAW_JUNCTION_STRUCT_TYPE:
|
|
|
|
|
#undef STRUCT
|
|
|
|
|
#define STRUCT ((DrawJunctionStruct*)DrawItem)
|
|
|
|
|
item = new DanglingEndHandle(JUNCTION_END);
|
|
|
|
|
item->m_Item = DrawItem;
|
|
|
|
|
item->m_Pos = STRUCT->m_Pos;
|
|
|
|
|
if ( lastitem ) lastitem->m_Pnext = item;
|
|
|
|
|
else StartList = item;
|
|
|
|
|
lastitem = item;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DRAW_BUSENTRY_STRUCT_TYPE:
|
|
|
|
|
#undef STRUCT
|
|
|
|
|
#define STRUCT ((DrawBusEntryStruct*)DrawItem)
|
|
|
|
|
item = new DanglingEndHandle(ENTRY_END);
|
|
|
|
|
item->m_Item = DrawItem;
|
|
|
|
|
item->m_Pos = STRUCT->m_Pos;
|
|
|
|
|
if ( lastitem ) lastitem->m_Pnext = item;
|
|
|
|
|
else StartList = item;
|
|
|
|
|
lastitem = item;
|
|
|
|
|
item = new DanglingEndHandle(ENTRY_END);
|
|
|
|
|
item->m_Item = DrawItem;
|
|
|
|
|
item->m_Pos = STRUCT->m_End();
|
|
|
|
|
lastitem->m_Pnext = item;
|
|
|
|
|
lastitem = item;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DRAW_LIB_ITEM_STRUCT_TYPE:
|
|
|
|
|
{
|
|
|
|
|
#undef STRUCT
|
|
|
|
|
#define STRUCT ((EDA_SchComponentStruct*)DrawItem)
|
|
|
|
|
EDA_LibComponentStruct * Entry;
|
|
|
|
|
Entry = FindLibPart( STRUCT->m_ChipName, wxEmptyString, FIND_ROOT);
|
|
|
|
|
if( Entry == NULL ) break;
|
|
|
|
|
LibEDA_BaseStruct * DrawLibItem = Entry->m_Drawings;
|
|
|
|
|
for ( ; DrawLibItem != NULL; DrawLibItem = DrawLibItem->Next())
|
|
|
|
|
{
|
|
|
|
|
if(DrawLibItem->m_StructType != COMPONENT_PIN_DRAW_TYPE) continue;
|
|
|
|
|
|
|
|
|
|
LibDrawPin * Pin = (LibDrawPin *) DrawLibItem;
|
|
|
|
|
|
|
|
|
|
if( Pin->m_Unit && DrawLibItem->m_Unit &&
|
|
|
|
|
(DrawLibItem->m_Unit != Pin->m_Unit) )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if( Pin->m_Convert && DrawLibItem->m_Convert &&
|
|
|
|
|
(DrawLibItem->m_Convert != Pin->m_Convert) )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
item = new DanglingEndHandle(PIN_END);
|
|
|
|
|
item->m_Item = Pin;
|
|
|
|
|
item->m_Pos = ReturnPinPhysicalPosition( Pin,STRUCT);
|
|
|
|
|
if ( lastitem ) lastitem->m_Pnext = item;
|
|
|
|
|
else StartList = item;
|
|
|
|
|
lastitem = item;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case DRAW_SHEET_STRUCT_TYPE:
|
|
|
|
|
{
|
|
|
|
|
#undef STRUCT
|
|
|
|
|
#define STRUCT ((DrawSheetStruct*)DrawItem)
|
|
|
|
|
DrawSheetLabelStruct * pinsheet = STRUCT->m_Label;
|
|
|
|
|
while(pinsheet)
|
|
|
|
|
{
|
|
|
|
|
item = new DanglingEndHandle(SHEET_LABEL_END);
|
|
|
|
|
item->m_Item = pinsheet;
|
|
|
|
|
item->m_Pos = pinsheet->m_Pos;
|
|
|
|
|
if ( lastitem ) lastitem->m_Pnext = item;
|
|
|
|
|
else StartList = item;
|
|
|
|
|
lastitem = item;
|
|
|
|
|
pinsheet = (DrawSheetLabelStruct*)pinsheet->Pnext;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return StartList;
|
|
|
|
|
}
|