kicad/eeschema/dangling_ends.cpp

410 lines
11 KiB
C++
Raw Blame History

/*********************/
/* 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;
}