kicad/eeschema/locate.cpp

1102 lines
32 KiB
C++

/******************************************************/
/* Routines de localisation d'un element d'un schema. */
/******************************************************/
#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "program.h"
#include "libcmp.h"
#include "general.h"
#include "trigo.h"
#include "macros.h"
#include "protos.h"
/* Routines exportees */
int distance(int dx, int dy, int spot_cX, int spot_cY, int seuil);
/* Routines Locales */
static EDA_BaseStruct *LastSnappedStruct = NULL;
static int PickedBoxMinX, PickedBoxMinY, PickedBoxMaxX, PickedBoxMaxY ;
static bool IsBox1InBox2( int StartX1, int StartY1, int EndX1, int EndY1,
int StartX2, int StartY2, int EndX2, int EndY2 );
static bool IsPointInBox( int pX, int pY,
int BoxX1, int BoxY1, int BoxX2, int BoxY2 );
static bool IsPointOnSegment( int pX, int pY,
int SegmX1, int SegmY1, int SegmX2, int SegmY2, int seuil = 0);
static bool SnapPoint2(const wxPoint & PosRef, int SearchMask,
EDA_BaseStruct *DrawList, DrawPickedStruct *DontSnapList, int zoom_value);
/*********************************************************************/
EDA_SchComponentStruct * LocateSmallestComponent( SCH_SCREEN * Screen )
/*********************************************************************/
/* Search the smaller (considering its area) component under the mouse cursor or the pcb cursor
If more than 1 component is found, a pointer to the smaller component is returned
*/
{
EDA_SchComponentStruct * DrawLibItem = NULL, * LastDrawLibItem = NULL;
EDA_BaseStruct *DrawList;
EDA_Rect BoundaryBox;
float sizeref = 0, sizecurr;
DrawList = Screen->EEDrawList;
while ( DrawList )
{
if( ( SnapPoint2(Screen->m_MousePosition, LIBITEM,
DrawList,NULL, Screen->GetZoom())) == FALSE )
{
if( ( SnapPoint2(Screen->m_Curseur, LIBITEM,
DrawList,NULL, Screen->GetZoom())) == FALSE ) break;
}
DrawLibItem = (EDA_SchComponentStruct *) LastSnappedStruct;
DrawList = DrawLibItem->Pnext;
if ( LastDrawLibItem == NULL ) // First time a component is located
{
LastDrawLibItem = DrawLibItem;
BoundaryBox = LastDrawLibItem->GetBoundaryBox();
sizeref = ABS((float)BoundaryBox.GetWidth() * BoundaryBox.GetHeight());
}
else
{
BoundaryBox = DrawLibItem->GetBoundaryBox();
sizecurr = ABS((float)BoundaryBox.GetWidth() * BoundaryBox.GetHeight());
if ( sizeref > sizecurr ) // a smallest component is found
{
sizeref = sizecurr;
LastDrawLibItem = DrawLibItem;
}
}
}
return LastDrawLibItem;
}
/* SearchMask = (bitwise OR):
LIBITEM
WIREITEM
BUSITEM
RACCORDITEM
JUNCTIONITEM
DRAWITEM
TEXTITEM
LABELITEM
SHEETITEM
MARKERITEM
NOCONNECTITEM
SEARCH_PINITEM
SHEETLABELITEM
FIELDCMPITEM
if EXCLUDE_WIRE_BUS_ENDPOINTS is set, in wire ou bus search and locate,
start and end points are not included in search
if WIRE_BUS_ENDPOINTS_ONLY is set, in wire ou bus search and locate,
only start and end points are included in search
Return:
-Bloc search:
pointeur sur liste de pointeurs de structures si Plusieurs
structures selectionnees.
pointeur sur la structure si 1 seule
Positon serach:
pointeur sur la structure.
Si pas de structures selectionnees: retourne NULL
*/
/***********************************************************************/
EDA_BaseStruct * PickStruct(const wxPoint & refpos,
EDA_BaseStruct *DrawList, int SearchMask )
/************************************************************************/
/* Search an item at pos pos
*/
{
bool Snapped;
int zoom = ActiveScreen->GetZoom();
if ( DrawList == NULL ) return NULL;
if( (Snapped = SnapPoint2(refpos, SearchMask,
DrawList,NULL, zoom)) != FALSE)
{
return( LastSnappedStruct);
}
return( NULL );
}
/***********************************************************************/
EDA_BaseStruct * PickStruct( EDA_Rect & block,
EDA_BaseStruct *DrawList, int SearchMask )
/************************************************************************/
/* Search items in block
*/
{
int x, y, OrigX, OrigY;
DrawPickedStruct *PickedList = NULL, *PickedItem;
EDA_BaseStruct *DrawStruct;
OrigX = block.GetX();
OrigY = block.GetY();
x = block.GetRight();
y = block.GetBottom();
if (x < OrigX) EXCHG(x, OrigX);
if (y < OrigY) EXCHG(y, OrigY);
for (DrawStruct = DrawList; DrawStruct != NULL; DrawStruct = DrawStruct->Pnext)
{
if( DrawStructInBox(OrigX, OrigY, x, y, DrawStruct) )
{
/* Put this structure in the picked list: */
PickedItem = new DrawPickedStruct(DrawStruct);
PickedItem->Pnext = PickedList;
PickedList = PickedItem;
}
}
if (PickedList && PickedList->Pnext == NULL)
{
/* Only one item was picked - convert to scalar form (no list): */
PickedItem = PickedList;
PickedList = (DrawPickedStruct *) PickedList->m_PickedStruct;
delete PickedItem;
}
if (PickedList != NULL)
{
PickedBoxMinX = OrigX; PickedBoxMinY = OrigY;
PickedBoxMaxX = x; PickedBoxMaxY = y;
}
return PickedList;
}
/*****************************************************************************
* Routine to search all objects for the closest point to a given point, in *
* drawing space, and snap it to that points if closer than SnapDistance. *
* Note we use L1 norm as distance measure, as it is the fastest. *
* This routine updates LastSnappedStruct to the last object used in to snap *
* a point. This variable is global to this module only (see above). *
* If DontSnapList is not NULL, structes in this list are skipped. *
* The routine returns TRUE if point was snapped. *
*****************************************************************************/
bool SnapPoint2(const wxPoint & PosRef, int SearchMask,
EDA_BaseStruct *DrawList, DrawPickedStruct *DontSnapList, int zoom_value)
{
int i, *Points, x = PosRef.x, y = PosRef.y;
int x1, y1, x2, y2, NumOfPoints2;
DrawPickedStruct *DontSnap;
int dx, dy;
for (; DrawList != NULL; DrawList = DrawList->Pnext)
{
/* Make sure this structure is NOT in the dont snap list: */
DontSnap = DontSnapList;
for( ; DontSnap != NULL; DontSnap = (DrawPickedStruct *)DontSnap->Pnext)
if (DontSnap->m_PickedStruct == DrawList) break;
if(DontSnap) if (DontSnap->m_PickedStruct == DrawList) continue;
switch (DrawList->m_StructType)
{
case DRAW_POLYLINE_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawPolylineStruct *) DrawList)
if( !(SearchMask & (DRAWITEM|WIREITEM|BUSITEM)) ) break;
Points = STRUCT->m_Points;
NumOfPoints2 = STRUCT->m_NumOfPoints * 2;
for (i = 0; i < NumOfPoints2 - 2; i += 2)
{
x1 = Points[i]; y1 = Points[i+1];
x2 = Points[i+2]; y2 = Points[i+3];
if (IsPointOnSegment(x,y, x1, y1, x2, y2) )
{
LastSnappedStruct = DrawList;
return(TRUE);
}
}
break;
case DRAW_SEGMENT_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((EDA_DrawLineStruct *) DrawList)
if( !(SearchMask & (DRAWITEM|WIREITEM|BUSITEM)) ) break;
if (IsPointOnSegment(x,y, STRUCT->m_Start.x,STRUCT->m_Start.y ,
STRUCT->m_End.x, STRUCT->m_End.y) )
{
if( ((SearchMask & DRAWITEM) && (STRUCT->m_Layer == LAYER_NOTES)) ||
((SearchMask & WIREITEM) && (STRUCT->m_Layer == LAYER_WIRE)) ||
((SearchMask & BUSITEM) && (STRUCT->m_Layer == LAYER_BUS))
)
{
if (SearchMask & EXCLUDE_WIRE_BUS_ENDPOINTS)
{
if ( x == STRUCT->m_Start.x && y == STRUCT->m_Start.y )
break;
if ( x == STRUCT->m_End.x && y == STRUCT->m_End.y )
break;
}
if (SearchMask & WIRE_BUS_ENDPOINTS_ONLY)
{
if ( ! STRUCT->IsOneEndPointAt(wxPoint(x, y)) ) break;
}
LastSnappedStruct = DrawList;
return(TRUE);
}
}
break;
case DRAW_BUSENTRY_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawBusEntryStruct *) DrawList)
if( !(SearchMask & (RACCORDITEM)) ) break;
if (IsPointOnSegment(x,y, STRUCT->m_Pos.x,STRUCT->m_Pos.y,
STRUCT->m_End().x, STRUCT->m_End().y) )
{
LastSnappedStruct = DrawList;
return(TRUE);
}
break;
case DRAW_JUNCTION_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawJunctionStruct *) DrawList)
if( !(SearchMask & JUNCTIONITEM) )break;
dx = DRAWJUNCTION_SIZE / 2;
x1 = STRUCT->m_Pos.x - dx;
y1 = STRUCT->m_Pos.y - dx;
x2 = STRUCT->m_Pos.x + dx;
y2 = STRUCT->m_Pos.y + dx;
if(IsPointInBox(x, y, x1,y1, x2,y2) )
{
LastSnappedStruct = DrawList;
return(TRUE);
}
break;
case DRAW_NOCONNECT_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawNoConnectStruct *) DrawList)
if( !(SearchMask & NOCONNECTITEM) )break;
dx = (DRAWNOCONNECT_SIZE*zoom_value) / 2;
x1 = STRUCT->m_Pos.x - dx;
y1 = STRUCT->m_Pos.y - dx;
x2 = STRUCT->m_Pos.x + dx;
y2 = STRUCT->m_Pos.y + dx;
if(IsPointInBox(x, y, x1,y1, x2,y2) )
{
LastSnappedStruct = DrawList;
return(TRUE);
}
break;
case DRAW_MARKER_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawMarkerStruct *) DrawList)
if( !(SearchMask & MARKERITEM) )break;
dx = (DRAWMARKER_SIZE*zoom_value) / 2;
x1 = STRUCT->m_Pos.x - dx;
y1 = STRUCT->m_Pos.y - dx;
x2 = STRUCT->m_Pos.x + dx;
y2 = STRUCT->m_Pos.y + dx;
if(IsPointInBox(x, y, x1,y1, x2,y2) )
{
LastSnappedStruct = DrawList;
return(TRUE);
}
break;
case DRAW_LABEL_STRUCT_TYPE:
case DRAW_TEXT_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawTextStruct *) DrawList)
if( !(SearchMask & (TEXTITEM|LABELITEM)) ) break;
dx = STRUCT->m_Size.x * STRUCT->GetLength();
dy = STRUCT->m_Size.y;
x1 = x2 = STRUCT->m_Pos.x;
y1 = y2 = STRUCT->m_Pos.y;
switch( STRUCT->m_Orient)
{
case 0 : /* HORIZONTAL */
x2 += dx; y2 -= dy;
break;
case 1 : /* VERTICAL UP */
x2 -= dy; y2 -= dx;
break;
case 2 : /* horizontal inverse */
x2 -= dx; y2 += dy;
break;
case 3 : /* vertical DOWN */
x2 += dy; y2 += dx;
break;
}
if(IsPointInBox(x, y, x1,y1, x2,y2) )
{
LastSnappedStruct = DrawList;
return(TRUE);
}
break;
case DRAW_GLOBAL_LABEL_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawGlobalLabelStruct *) DrawList)
if( !(SearchMask & LABELITEM) ) break;
dx = STRUCT->m_Size.x * ( STRUCT->GetLength() + 1 ); /* longueur */
dy = STRUCT->m_Size.y / 2; /* Demi hauteur */
x1 = x2 = STRUCT->m_Pos.x;
y1 = y2 = STRUCT->m_Pos.y;
switch( STRUCT->m_Orient)
{
case 0 : /* HORIZONTAL */
x2 -= dx; y2 += dy; y1 -= dy;
break;
case 1 : /* VERTICAL UP */
x1 -= dy; x2 += dy; y2 += dx;
break;
case 2 : /* horizontal inverse */
x2 += dx; y2 += dy; y1 -= dy;
break;
case 3 : /* vertical DOWN */
x1 -= dy; x2 += dy; y2 -= dx;
break;
}
if(IsPointInBox(x, y, x1,y1, x2,y2) )
{
LastSnappedStruct = DrawList;
return(TRUE);
}
break;
case DRAW_LIB_ITEM_STRUCT_TYPE:
if( !(SearchMask & (LIBITEM|FIELDCMPITEM) ) ) break;
if ( SearchMask & FIELDCMPITEM )
{
PartTextStruct * Field;
EDA_SchComponentStruct * DrawLibItem = (EDA_SchComponentStruct *) DrawList;
for ( i = REFERENCE; i < NUMBER_OF_FIELDS; i++ )
{
Field = &DrawLibItem->m_Field[i];
if ( (Field->m_Attributs & TEXT_NO_VISIBLE) ) continue;
if ( Field->IsVoid() ) continue;
EDA_Rect BoundaryBox = Field->GetBoundaryBox();
if(BoundaryBox.Inside(x, y) )
{
LastSnappedStruct = Field;
return TRUE;
}
}
}
else
{
#undef STRUCT
#define STRUCT ((EDA_SchComponentStruct *) DrawList)
EDA_Rect BoundaryBox = STRUCT->GetBoundaryBox();
if ( BoundaryBox.Inside(x, y) )
{
LastSnappedStruct = DrawList;
return TRUE;
}
}
break;
case DRAW_SHEET_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawSheetStruct *) DrawList)
if( !(SearchMask & SHEETITEM) ) break;
/* Recalcul des coordonnees de l'encadrement du composant */
x1 = STRUCT->m_Pos.x;
y1 = STRUCT->m_Pos.y;
x2 = STRUCT->m_Pos.x + STRUCT->m_Size.x;
y2 = STRUCT->m_Pos.y + STRUCT->m_Size.y;
if(IsPointInBox(x, y, x1, y1, x2, y2) )
{
LastSnappedStruct = DrawList;
return TRUE;
}
break;
case DRAW_PICK_ITEM_STRUCT_TYPE : break;
default:
{
wxString msg;
msg.Printf(wxT("SnapPoint2() error: unexpected strct type %d ("), DrawList->m_StructType);
msg << DrawList->ReturnClassName() << wxT(")");
DisplayError(NULL, msg);
break;
}
}
}
return FALSE;
}
/*****************************************************************************
* Routine to test if an object has non empty intersection with the box *
* defined by x1/y1 and x2/y2 (x1 < x2, y1 < y2), and return TRUE if so. This *
* routine is used to pick all points in a given box. *
*****************************************************************************/
bool DrawStructInBox(int x1, int y1, int x2, int y2,
EDA_BaseStruct *DrawStruct)
{
int i, *Points, xt1, yt1, xt2, yt2, NumOfPoints2;
int dx, dy;
wxString msg;
switch (DrawStruct->m_StructType)
{
case DRAW_POLYLINE_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawPolylineStruct *) DrawStruct)
Points = STRUCT->m_Points;
NumOfPoints2 = STRUCT->m_NumOfPoints * 2;
for (i = 0; i < NumOfPoints2; i += 2)
{
if (Points[i] >= x1 && Points[i] <= x2 &&
Points[i+1] >= y1 && Points[i+1] <=y2) return TRUE;
}
break;
case DRAW_SEGMENT_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((EDA_DrawLineStruct *) DrawStruct)
if( STRUCT->m_Start.x >= x1 && STRUCT->m_Start.x <= x2 &&
STRUCT->m_Start.y >= y1 && STRUCT->m_Start.y <=y2) return TRUE;
if( (STRUCT->m_End.x >= x1) && (STRUCT->m_End.x <= x2) &&
(STRUCT->m_End.y >= y1) && (STRUCT->m_End.y <=y2) ) return TRUE;
break;
case DRAW_BUSENTRY_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawBusEntryStruct *) DrawStruct)
if( STRUCT->m_Pos.x >= x1 && STRUCT->m_Pos.x <= x2 &&
STRUCT->m_Pos.y >= y1 && STRUCT->m_Pos.y <=y2)
return TRUE;
if( (STRUCT->m_End().x >= x1) && ( STRUCT->m_End().x <= x2) &&
( STRUCT->m_End().y >= y1) && ( STRUCT->m_End().y <=y2) )
return TRUE;
break;
case DRAW_JUNCTION_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawJunctionStruct *) DrawStruct)
if( (STRUCT->m_Pos.x >= x1) && (STRUCT->m_Pos.x <= x2) &&
(STRUCT->m_Pos.y >= y1) && (STRUCT->m_Pos.y <= y2) )
return TRUE;
break;
case DRAW_NOCONNECT_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawNoConnectStruct *) DrawStruct)
if( (STRUCT->m_Pos.x >= x1) && (STRUCT->m_Pos.x <= x2) &&
(STRUCT->m_Pos.y >= y1) && (STRUCT->m_Pos.y <= y2) )
return TRUE;
break;
case DRAW_MARKER_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawMarkerStruct *) DrawStruct)
if( (STRUCT->m_Pos.x >= x1) && (STRUCT->m_Pos.x <= x2) &&
(STRUCT->m_Pos.y >= y1) && (STRUCT->m_Pos.y <= y2) )
return TRUE;
break;
case DRAW_LABEL_STRUCT_TYPE:
case DRAW_TEXT_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawTextStruct *) DrawStruct)
dx = STRUCT->m_Size.x * STRUCT->GetLength();
dy = STRUCT->m_Size.y;
xt1 = xt2 = STRUCT->m_Pos.x;
yt1 = yt2 = STRUCT->m_Pos.y;
switch( STRUCT->m_Orient)
{
case 0 : /* HORIZONTAL */
xt2 += dx; yt2 -= dy;
break;
case 1 : /* VERTICAL UP */
xt2 -= dy; yt2 -= dx;
break;
case 2 : /* horizontal inverse */
xt2 -= dx; yt2 += dy;
break;
case 3 : /* vertical DOWN */
xt2 += dy; yt2 += dx;
break;
}
if( IsBox1InBox2(xt1,yt1, xt2, yt2, x1, y1, x2, y2) ) return TRUE;
break;
case DRAW_GLOBAL_LABEL_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ((DrawGlobalLabelStruct *) DrawStruct)
dx = STRUCT->m_Size.x * ( STRUCT->GetLength() + 1); /* longueur totale */
dy = STRUCT->m_Size.y / 2; /* Demi hauteur */
xt1 = xt2 = STRUCT->m_Pos.x;
yt1 = yt2 = STRUCT->m_Pos.y;
switch( STRUCT->m_Orient)
{
case 0 : /* HORIZONTAL */
xt2 -= dx; yt2 += dy; yt1 -= dy;
break;
case 1 : /* VERTICAL UP */
xt1 -= dy; xt2 += dy; yt2 += dx;
break;
case 2 : /* horizontal inverse */
xt2 += dx; yt2 += dy; yt1 -= dy;
break;
case 3 : /* vertical DOWN */
xt1 -= dy; xt2 += dy; yt2 -= dx;
break;
}
if( IsBox1InBox2(xt1,yt1, xt2, yt2, x1, y1, x2, y2) ) return TRUE;
break;
case DRAW_LIB_ITEM_STRUCT_TYPE:
{
#undef STRUCT
#define STRUCT ((EDA_SchComponentStruct *) DrawStruct)
EDA_Rect BoundaryBox = STRUCT->GetBoundaryBox();
xt1 = BoundaryBox.GetX();
yt1 = BoundaryBox.GetY();
xt2 = BoundaryBox.GetRight();
yt2 = BoundaryBox.GetBottom();
if( IsBox1InBox2(xt1,yt1, xt2, yt2, x1, y1, x2, y2) ) return TRUE;
break;
}
case DRAW_SHEET_STRUCT_TYPE :
#undef STRUCT
#define STRUCT ((DrawSheetStruct *) DrawStruct)
/* Recalcul des coordonnees de l'encadrement du composant */
xt1 = STRUCT->m_Pos.x;
yt1 = STRUCT->m_Pos.y;
xt2 = STRUCT->m_Pos.x + STRUCT->m_Size.x;
yt2 = STRUCT->m_Pos.y + STRUCT->m_Size.y;
if( IsBox1InBox2(xt1,yt1, xt2, yt2, x1, y1, x2, y2) )
return TRUE;
break;
case DRAW_SHEETLABEL_STRUCT_TYPE : break;
case DRAW_PICK_ITEM_STRUCT_TYPE : break;
default:
msg.Printf(
wxT("DrawStructInBox() Err: unexpected StructType %d ("),
DrawStruct->m_StructType );
msg << DrawStruct->ReturnClassName() << wxT(")");
DisplayError(NULL, msg );
break;
}
return FALSE;
}
/****************************************************************************/
static bool IsBox1InBox2( int StartX1, int StartY1, int EndX1, int EndY1,
int StartX2, int StartY2, int EndX2, int EndY2 )
/****************************************************************************/
/* Routine detectant que le rectangle 1 (Box1) et le rectangle 2 (Box2) se
recouvrent.
Retourne TRUE ou FALSE.
On Considere ici qu'il y a recouvrement si l'un au moins des coins
d'un 'Box' est compris dans l'autre
*/
{
int cX, cY;
if(StartX1 > EndX1) EXCHG(StartX1, EndX1);
if(StartX2 > EndX2) EXCHG(StartX2, EndX2);
if(StartY1 > EndY1) EXCHG(StartY1, EndY1);
if(StartY2 > EndY2) EXCHG(StartY2, EndY2);
/* Tst des 4 coins du rectangle 1 */
cX = StartX1; cY = StartY1; /* 1er coin */
if( (cX >= StartX2) && (cX <= EndX2) && (cY >= StartY2) && (cY <= EndY2) )
return(TRUE);
cX = EndX1; cY = StartY1; /* 2er coin */
if( (cX >= StartX2) && (cX <= EndX2) && (cY >= StartY2) && (cY <= EndY2) )
return(TRUE);
cX = EndX1; cY = EndY1; /* 3eme coin */
if( (cX >= StartX2) && (cX <= EndX2) && (cY >= StartY2) && (cY <= EndY2) )
return(TRUE);
cX = StartX1; cY = EndY1; /* 4eme coin */
if( (cX >= StartX2) && (cX <= EndX2) && (cY >= StartY2) && (cY <= EndY2) )
return(TRUE);
/* Tst des 4 coins du rectangle 2 */
cX = StartX2; cY = StartY2; /* 1er coin */
if( (cX >= StartX1) && (cX <= EndX1) && (cY >= StartY1) && (cY <= EndY1) )
return(TRUE);
cX = EndX2; cY = StartY2; /* 2er coin */
if( (cX >= StartX1) && (cX <= EndX1) && (cY >= StartY1) && (cY <= EndY1) )
return(TRUE);
cX = EndX2; cY = EndY2; /* 3er coin */
if( (cX >= StartX1) && (cX <= EndX1) && (cY >= StartY1) && (cY <= EndY1) )
return(TRUE);
cX = StartX2; cY = EndY2; /* 4er coin */
if( (cX >= StartX1) && (cX <= EndX1) && (cY >= StartY1) && (cY <= EndY1) )
return(TRUE);
return(FALSE);
}
/**********************************************************************/
static bool IsPointInBox( int pX, int pY,
int BoxX1, int BoxY1, int BoxX2, int BoxY2 )
/**********************************************************************/
/* Routine detectant que le point pX,pY est dans le rectangle (Box)
Retourne TRUE ou FALSE.
*/
{
if(BoxX1 > BoxX2) EXCHG(BoxX1, BoxX2);
if(BoxY1 > BoxY2) EXCHG(BoxY1, BoxY2);
if( (pX >= BoxX1) && (pX <= BoxX2) && (pY >= BoxY1) && (pY <= BoxY2) )
return(TRUE);
else return(FALSE);
}
/********************************************************************************/
static bool IsPointOnSegment( int pX, int pY,
int SegmX1, int SegmY1, int SegmX2, int SegmY2, int seuil )
/********************************************************************************/
/* Routine detectant que le point pX,pY est sur le Segment X1,Y1 a X2,Y2
Retourne TRUE ou FALSE.
*/
{
/* Recalcul des coord avec SegmX1, SegmX2 comme origine */
pX -= SegmX1; pY -= SegmY1;
SegmX2 -= SegmX1; SegmY2 -= SegmY1;
if( distance( SegmX2, SegmY2, pX, pY, seuil ) ) return(TRUE);
else return(FALSE);
}
/*********************************************************************************/
LibEDA_BaseStruct * LocateDrawItem(SCH_SCREEN * Screen, const wxPoint & refpoint,
EDA_LibComponentStruct * LibEntry, int Unit, int Convert, int masque)
/*********************************************************************************/
/* Routine de localisation d'un element de dessin de symbole( sauf pins )
Unit = Unite d'appartenance (si Unit = 0, recherche sur toutes unites)
Convert = Conversion d'appartenance (si Convert = 0, recherche sur
toutes variantes)
*/
{
int x, y, dx, dy, ii, *ptpoly;
int px, py;
LibEDA_BaseStruct * DrawItem;
int seuil;
if( LibEntry == NULL ) return(NULL);
if ( LibEntry->Type != ROOT )
{
DisplayError(NULL, wxT("Error in LocateDrawItem: Entry is ALIAS"));
return(NULL);
}
DrawItem = LibEntry->m_Drawings;
seuil = 3; /* Tolerance: 1/2 pas de petite grille */
px = refpoint.x;
py = refpoint.y;
for( ; DrawItem != NULL ; DrawItem = DrawItem->Next() )
{
if(Unit && DrawItem->m_Unit && (Unit != DrawItem->m_Unit) ) continue;
if(Convert && DrawItem->m_Convert && (Convert != DrawItem->m_Convert) )
continue;
switch ( DrawItem->m_StructType )
{
case COMPONENT_ARC_DRAW_TYPE:
{
LibDrawArc * Arc = (LibDrawArc *) DrawItem;
if( (masque & LOCATE_COMPONENT_ARC_DRAW_TYPE) == 0) break;
dx = px - Arc->m_Pos.x;
dy = py + Arc->m_Pos.y;
ii = (int)sqrt( dx*dx + dy*dy);
if ( abs(ii - Arc->m_Rayon) <= seuil) return( DrawItem);
}
break;
case COMPONENT_CIRCLE_DRAW_TYPE:
{
LibDrawCircle * Circle = (LibDrawCircle *) DrawItem;
if( (masque & LOCATE_COMPONENT_CIRCLE_DRAW_TYPE) == 0) break;
dx = px - Circle->m_Pos.x;
dy = py + Circle->m_Pos.y;
ii = (int)sqrt( dx*dx + dy*dy);
if ( abs(ii - Circle->m_Rayon) <= seuil) return( DrawItem);
}
break;
case COMPONENT_RECT_DRAW_TYPE:
{ // Locate a rect if the mouse cursor is on a segment
LibDrawSquare * Square = (LibDrawSquare *) DrawItem;
if( (masque & LOCATE_COMPONENT_RECT_DRAW_TYPE) == 0) break;
if(IsPointOnSegment(px,py, // locate lower segment
Square->m_Pos.x, - Square->m_Pos.y,
Square->m_End.x, - Square->m_Pos.y, seuil) )
return(DrawItem);
if(IsPointOnSegment(px, py, // locate right segment
Square->m_End.x, - Square->m_Pos.y,
Square->m_End.x, - Square->m_End.y, seuil) )
return(DrawItem);
if(IsPointOnSegment(px, py, // locate upper segment
Square->m_End.x, - Square->m_End.y,
Square->m_Pos.x, - Square->m_End.y, seuil) )
return(DrawItem);
if(IsPointOnSegment(px, py, // locate left segment
Square->m_Pos.x, - Square->m_End.y,
Square->m_Pos.x, - Square->m_Pos.y, seuil) )
return(DrawItem);
}
break;
case COMPONENT_POLYLINE_DRAW_TYPE:
{
LibDrawPolyline * polyline = (LibDrawPolyline *) DrawItem;
if( (masque & LOCATE_COMPONENT_POLYLINE_DRAW_TYPE) == 0) break;
ptpoly = polyline->PolyList;
for( ii = polyline->n-1; ii > 0; ii--, ptpoly += 2)
{
if(IsPointOnSegment(px, py,
ptpoly[0], - ptpoly[1], ptpoly[2], - ptpoly[3], seuil) )
return(DrawItem);
}
}
break;
case COMPONENT_LINE_DRAW_TYPE:
{
LibDrawSegment * Segment = (LibDrawSegment *) DrawItem;
if( (masque & LOCATE_COMPONENT_LINE_DRAW_TYPE) == 0) break;
if(IsPointOnSegment(px, py,
Segment->m_Pos.x, - Segment->m_Pos.y,
Segment->m_End.x, - Segment->m_End.y, seuil) )
return(DrawItem);
}
break;
case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE:
{
LibDrawText * Text = (LibDrawText *) DrawItem;
if( (masque & LOCATE_COMPONENT_GRAPHIC_TEXT_DRAW_TYPE) == 0) break;
ii = Text->m_Text.Len(); if ( ii < 2 ) ii = 2;
dx = (Text->m_Size.x * ii) / 2;
dy = Text->m_Size.y / 2;
if(Text->m_Horiz == TEXT_ORIENT_VERT)
{
EXCHG(dx,dy);
}
x = px - Text->m_Pos.x;
y = py + Text->m_Pos.y;
if( (abs(x) <= dx) && (abs(y) <= dy) )
return(DrawItem); /* Texte trouve */
}
break;
default:
;
}
}
return(NULL);
}
/****************************************************************/
int distance(int dx, int dy, int spot_cX, int spot_cY, int seuil)
/****************************************************************/
/*
Calcul de la distance du point spot_cx,spot_cy a un segment de droite,
d'origine 0,0 et d'extremite dx, dy;
retourne:
0 si distance > seuil
1 si distance <= seuil
Variables utilisees ( sont ramenees au repere centre sur l'origine du segment)
dx, dy = coord de l'extremite segment.
spot_cX,spot_cY = coord du curseur souris
la recherche se fait selon 4 cas:
segment horizontal
segment vertical
segment quelconque
*/
{
int cXrot, cYrot , /* coord du point (souris) dans le repere tourne */
segX, segY; /* coord extremite segment tj >= 0 */
int pointX, pointY; /* coord point a tester dans repere modifie dans lequel
segX et segY sont >=0 */
segX = dx ; segY = dy; pointX = spot_cX ; pointY = spot_cY ;
/*Recalcul coord pour que le segment soit dans 1er quadrant (coord >= 0)*/
if (segX < 0) /* mise en0 par symetrie par rapport a l'axe Y */
{
segX = -segX ; pointX = - pointX ;
}
if (segY < 0) /* mise en > 0 par symymetrie par rapport a l'axe X */
{
segY = -segY ; pointY = -pointY ;
}
if ( segY == 0 ) /* piste Horizontale */
{
if(abs(pointY) <= seuil )
{
if((pointX >= 0) && (pointX <= segX) ) return(1);
/* Etude des extremites : cercle de rayon seuil */
if( (pointX < 0) && (pointX >= -seuil) )
{
if( ((pointX * pointX) + (pointY*pointY)) <= (seuil*seuil) )
return(1);
}
if( (pointX > segX) && (pointX <= (segX+seuil)) )
{
if( (((pointX-segX) * (pointX-segX)) + (pointY*pointY)) <= (seuil*seuil) )
return(1);
}
}
}
else if ( segX == 0 ) /* piste verticale */
{
if( abs(pointX) <= seuil)
{
if((pointY >= 0 ) && (pointY <= segY) ) return(1);
if( (pointY < 0) && (pointY >= -seuil) )
{
if( ((pointY * pointY) + (pointX*pointX)) <= (seuil*seuil) )
return(1);
}
if( (pointY > segY) && (pointY <= (segY+seuil)) )
{
if( ( ((pointY-segY) * (pointY-segY)) + (pointX*pointX)) <= (seuil*seuil) )
return(1);
}
}
}
else /* orientation quelconque */
{
/* On fait un changement d'axe (rotation) de facon a ce que le segment
de piste soit horizontal dans le nouveau repere */
int angle;
angle = (int)( atan2((float)segY, (float)segX) * 1800 / M_PI) ;
cXrot = pointX; cYrot = pointY;
RotatePoint(&cXrot, &cYrot, angle); /* Rotation du point a tester */
RotatePoint(&segX, &segY, angle) ; /* Rotation du segment */
/*la piste est Horizontale , par suite des modifs de coordonnes
et d'axe, donc segX = longueur du segment */
if ( abs(cYrot) <= seuil ) /* ok sur axe vertical) */
{
if ((cXrot >= 0) && (cXrot <= segX) ) return(1) ;
/* Etude des extremites : cercle de rayon seuil */
if( (cXrot < 0) && (cXrot >= -seuil) )
{
if( ((cXrot * cXrot) + (cYrot*cYrot)) <= (seuil*seuil) )
return(1);
}
if( (cXrot > segX) && (cXrot <= (segX+seuil)) )
{
if( (((cXrot-segX) * (cXrot-segX)) + (cYrot*cYrot)) <= (seuil*seuil) )
return(1);
}
}
}
return(0) ;
}
/*******************************************************************/
LibEDA_BaseStruct * LocatePin( const wxPoint & RefPos,
EDA_LibComponentStruct * Entry,
int Unit, int convert, EDA_SchComponentStruct * DrawLibItem)
/*******************************************************************/
/* Routine de localisation d'une PIN de la PartLib pointee par Entry
retourne un pointeur sur la pin, ou NULL si pas trouve
Si Unit = 0, le numero d'unite n'est pas teste
Si convert = 0, le numero convert n'est pas teste
m_Transform = matrice de transformation.
Si NULL: matrice de transformation " normale" [1 , 0 , 0 , -1]
(la matrice de transformation " normale" etant [1 , 0 , 0 , -1]
la coord dy doit etre inversee).
PartX, PartY: coordonnees de positionnement du composant
*/
{
LibEDA_BaseStruct * DrawItem;
LibDrawPin * Pin;
int x1, y1, x2, y2;
if ( Entry == NULL ) return(NULL);
if ( Entry->Type != ROOT )
{
DisplayError(NULL, wxT("LocatePin() error: Entry is ALIAS"));
return(NULL);
}
DrawItem = Entry->m_Drawings;
for ( ; DrawItem != NULL; DrawItem = DrawItem->Next())
{
if(DrawItem->m_StructType == COMPONENT_PIN_DRAW_TYPE) /* Pin Trouvee */
{
Pin = (LibDrawPin *) DrawItem;
if( Unit && DrawItem->m_Unit && (DrawItem->m_Unit != Unit) )
continue;
if( convert && DrawItem->m_Convert && (DrawItem->m_Convert != convert) )
continue;
x2 = Pin->m_Pos.x;
y2 = Pin->m_Pos.y;
x1 = Pin->ReturnPinEndPoint().x;
y1 = Pin->ReturnPinEndPoint().y;
if(DrawLibItem == NULL )
{
y1 = -y1; y2 = -y2;
}
else
{
int x = x1, y = y1;
x1 = DrawLibItem->m_Pos.x + DrawLibItem->m_Transform[0][0] * x
+ DrawLibItem->m_Transform[0][1] * y;
y1 = DrawLibItem->m_Pos.y + DrawLibItem->m_Transform[1][0] * x
+ DrawLibItem->m_Transform[1][1] * y;
x = x2; y = y2;
x2 = DrawLibItem->m_Pos.x + DrawLibItem->m_Transform[0][0] * x
+ DrawLibItem->m_Transform[0][1] * y;
y2 = DrawLibItem->m_Pos.y + DrawLibItem->m_Transform[1][0] * x
+ DrawLibItem->m_Transform[1][1] * y;
}
if (x1 > x2 ) EXCHG(x1,x2); if (y1 > y2 ) EXCHG(y1,y2);
if( (RefPos.x >= x1) && (RefPos.x <= x2) &&
(RefPos.y >= y1) && (RefPos.y <= y2) )
return(DrawItem);
}
}
return(NULL);
}
/***********************************************************************************/
DrawSheetLabelStruct * LocateSheetLabel(DrawSheetStruct *Sheet, const wxPoint & pos)
/***********************************************************************************/
{
int size , dy, minx, maxx;
DrawSheetLabelStruct * SheetLabel;
SheetLabel = Sheet->m_Label;
while((SheetLabel) && (SheetLabel->m_StructType==DRAW_SHEETLABEL_STRUCT_TYPE))
{
size = ( SheetLabel->GetLength()+1 ) * SheetLabel->m_Size.x;
if (SheetLabel->m_Edge) size = -size ;
minx = SheetLabel->m_Pos.x; maxx = SheetLabel->m_Pos.x + size;
if( maxx < minx ) EXCHG(maxx,minx);
dy = SheetLabel->m_Size.x / 2;
if( (ABS(pos.y - SheetLabel->m_Pos.y) <= dy ) &&
(pos.x <= maxx) &&
(pos.x >= minx) )
return(SheetLabel);
SheetLabel = (DrawSheetLabelStruct *) SheetLabel->Pnext;
}
return(NULL);
}
/**************************************************************************/
LibDrawPin * LocateAnyPin(EDA_BaseStruct *DrawList, const wxPoint & RefPos,
EDA_SchComponentStruct ** libpart)
/**************************************************************************/
{
EDA_BaseStruct *DrawStruct;
EDA_LibComponentStruct * Entry;
EDA_SchComponentStruct * LibItem = NULL;
LibDrawPin * Pin = NULL;
for(DrawStruct = DrawList; DrawStruct != NULL; DrawStruct = DrawStruct->Pnext )
{
if( DrawStruct->m_StructType != DRAW_LIB_ITEM_STRUCT_TYPE )
continue;
LibItem = (EDA_SchComponentStruct *) DrawStruct;
Entry = FindLibPart( LibItem->m_ChipName.GetData(), wxEmptyString, FIND_ROOT);
if( Entry == NULL ) continue;
Pin = (LibDrawPin *) LocatePin(RefPos, Entry, LibItem->m_Multi,
LibItem->m_Convert, LibItem);
if( Pin ) break;
}
if ( libpart ) *libpart = LibItem;
return Pin;
}
/***************************************************************/
DrawSheetLabelStruct * LocateAnyPinSheet(const wxPoint & RefPos,
EDA_BaseStruct *DrawList)
/***************************************************************/
{
EDA_BaseStruct *DrawStruct;
DrawSheetLabelStruct * PinSheet = NULL;
for( DrawStruct = DrawList; DrawStruct != NULL; DrawStruct = DrawStruct->Pnext )
{
if( DrawStruct->m_StructType != DRAW_SHEET_STRUCT_TYPE )
continue;
PinSheet = LocateSheetLabel( (DrawSheetStruct *) DrawStruct,
RefPos);
if( PinSheet ) break;
}
return PinSheet;
}