/*********************/ /* 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ées pos est sur l'extrémité 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; }