466 lines
13 KiB
C++
466 lines
13 KiB
C++
/************************************************/
|
|
/* Locate items at the current cursor position. */
|
|
/************************************************/
|
|
|
|
#include "fctsys.h"
|
|
#include "common.h"
|
|
#include "class_drawpanel.h"
|
|
|
|
#include "pcbnew.h"
|
|
#include "gerbview.h"
|
|
#include "trigo.h"
|
|
#include "protos.h"
|
|
|
|
|
|
int ux0, uy0, dx, dy, spot_cX, spot_cY;
|
|
|
|
|
|
static TRACK* Locate_Zone( TRACK* start_adresse, int layer, int typeloc );
|
|
static TRACK* Locate_Zone( TRACK* start_adresse, wxPoint ref, int layer );
|
|
static TRACK* Locate_Pistes( TRACK* start_adresse,
|
|
int Layer,
|
|
int typeloc );
|
|
static TRACK* Locate_Pistes( TRACK* start_adresse,
|
|
wxPoint ref,
|
|
int Layer );
|
|
static DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int typeloc );
|
|
static TEXTE_PCB* Locate_Texte_Pcb( TEXTE_PCB* pt_txt_pcb, int typeloc );
|
|
static int distance( int seuil );
|
|
|
|
|
|
/* Macro for calculating the coordinates of the cursor position.
|
|
*/
|
|
#define SET_REF_POS( ref ) if( typeloc == CURSEUR_ON_GRILLE ) \
|
|
{ ref = ActiveScreen->m_Curseur; } \
|
|
else { ref = ActiveScreen->m_MousePosition; }
|
|
|
|
|
|
/* Display the character of the localized STRUCTURE and return a pointer
|
|
* to it.
|
|
*/
|
|
BOARD_ITEM* WinEDA_GerberFrame::Locate( int typeloc )
|
|
{
|
|
TEXTE_PCB* pt_texte_pcb;
|
|
TRACK* Track, * TrackLocate;
|
|
DRAWSEGMENT* DrawSegm;
|
|
int layer;
|
|
|
|
/* Locate tracks and vias, with priority to vias */
|
|
layer = GetScreen()->m_Active_Layer;
|
|
Track = Locate_Pistes( GetBoard()->m_Track, -1, typeloc );
|
|
if( Track != NULL )
|
|
{
|
|
TrackLocate = Track;
|
|
|
|
while( ( TrackLocate = Locate_Pistes( TrackLocate,
|
|
layer, typeloc ) ) != NULL )
|
|
{
|
|
Track = TrackLocate;
|
|
if( TrackLocate->Type() == TYPE_VIA )
|
|
break;
|
|
TrackLocate = TrackLocate->Next();
|
|
}
|
|
|
|
Track->DisplayInfo( this );
|
|
return Track;
|
|
}
|
|
|
|
|
|
pt_texte_pcb = Locate_Texte_Pcb(
|
|
(TEXTE_PCB*) GetBoard()->m_Drawings.GetFirst(), typeloc );
|
|
|
|
if( pt_texte_pcb )
|
|
{
|
|
pt_texte_pcb->DisplayInfo( this );
|
|
return pt_texte_pcb;
|
|
}
|
|
|
|
if( ( DrawSegm = Locate_Segment_Pcb( GetBoard(), typeloc ) ) != NULL )
|
|
{
|
|
return DrawSegm;
|
|
}
|
|
|
|
if( ( TrackLocate = Locate_Zone( GetBoard()->m_Zone,
|
|
GetScreen()->m_Active_Layer,
|
|
typeloc ) ) != NULL )
|
|
{
|
|
TrackLocate->DisplayInfo( this );
|
|
return TrackLocate;
|
|
}
|
|
|
|
MsgPanel->EraseMsgBox();
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* Locate of segments of pcb edge or draw as active layer.
|
|
* Returns:
|
|
* Pointer to START segment if found
|
|
* NULL if nothing found
|
|
*/
|
|
DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int typeloc )
|
|
{
|
|
BOARD_ITEM* PtStruct;
|
|
DRAWSEGMENT* pts;
|
|
wxPoint ref;
|
|
PCB_SCREEN* screen = (PCB_SCREEN*) ActiveScreen;
|
|
|
|
SET_REF_POS( ref );
|
|
|
|
PtStruct = Pcb->m_Drawings;
|
|
for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
|
|
{
|
|
if( PtStruct->Type() != TYPE_DRAWSEGMENT )
|
|
continue;
|
|
pts = (DRAWSEGMENT*) PtStruct;
|
|
ux0 = pts->m_Start.x;
|
|
uy0 = pts->m_Start.y;
|
|
|
|
dx = pts->m_End.x - ux0;
|
|
dy = pts->m_End.y - uy0;
|
|
spot_cX = ref.x - ux0;
|
|
spot_cY = ref.y - uy0;
|
|
|
|
if( pts->GetLayer() != screen->m_Active_Layer )
|
|
continue;
|
|
|
|
if( ( pts->m_Shape == S_CIRCLE ) || ( pts->m_Shape == S_ARC ) )
|
|
{
|
|
int rayon, dist, StAngle, EndAngle, MouseAngle;
|
|
rayon = (int) hypot( (double) (dx), (double) (dy) );
|
|
dist = (int) hypot( (double) (spot_cX), (double) (spot_cY) );
|
|
if( abs( rayon - dist ) <= ( pts->m_Width / 2 ) )
|
|
{
|
|
if( pts->m_Shape == S_CIRCLE )
|
|
return pts;
|
|
|
|
MouseAngle = (int) ArcTangente( spot_cY, spot_cX );
|
|
StAngle = (int) ArcTangente( dy, dx );
|
|
EndAngle = StAngle + pts->m_Angle;
|
|
|
|
if( EndAngle > 3600 )
|
|
{
|
|
StAngle -= 3600; EndAngle -= 3600;
|
|
}
|
|
if( ( MouseAngle >= StAngle ) && ( MouseAngle <= EndAngle ) )
|
|
return pts;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( distance( pts->m_Width / 2 ) )
|
|
return pts;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* 1 - Locate segment of track at current cursor position.
|
|
* 2 - Locate segment of track point by point.
|
|
* Ref_pX, ref_pY.r
|
|
*
|
|
* The search begins to address start_adresse
|
|
*/
|
|
TRACK* Locate_Pistes( TRACK* start_adresse, int Layer, int typeloc )
|
|
{
|
|
wxPoint ref;
|
|
|
|
SET_REF_POS( ref );
|
|
|
|
return Locate_Pistes( start_adresse, ref, Layer );
|
|
}
|
|
|
|
|
|
TRACK* Locate_Pistes( TRACK* start_adresse, wxPoint ref, int Layer )
|
|
{
|
|
TRACK* Track;
|
|
int l_piste; /* half-width of the track */
|
|
|
|
for( Track = start_adresse; Track != NULL; Track = Track->Next() )
|
|
{
|
|
if( Track->GetState( BUSY | DELETED ) )
|
|
continue;
|
|
/* Calculate coordinates of the test segment. */
|
|
l_piste = Track->m_Width >> 1;
|
|
ux0 = Track->m_Start.x;
|
|
uy0 = Track->m_Start.y;
|
|
dx = Track->m_End.x;
|
|
dy = Track->m_End.y;
|
|
|
|
dx -= ux0;
|
|
dy -= uy0;
|
|
spot_cX = ref.x - ux0;
|
|
spot_cY = ref.y - uy0;
|
|
|
|
if( Track->Type() == TYPE_VIA )
|
|
{
|
|
if( ( abs( spot_cX ) <= l_piste ) && ( abs( spot_cY ) <=l_piste ) )
|
|
{
|
|
return Track;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if( Layer >= 0 )
|
|
if( Track->GetLayer() != Layer )
|
|
continue;
|
|
if( distance( l_piste ) )
|
|
return Track;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* Locate zone area at the cursor position.
|
|
*
|
|
* The search begins to address start_adresse
|
|
*/
|
|
TRACK* Locate_Zone( TRACK* start_adresse, int layer, int typeloc )
|
|
{
|
|
wxPoint ref;
|
|
|
|
SET_REF_POS( ref );
|
|
|
|
return Locate_Zone( start_adresse, ref, layer );
|
|
}
|
|
|
|
|
|
/*
|
|
* Locate zone area at point.
|
|
*
|
|
* The search begins to address start_adresse
|
|
*/
|
|
TRACK* Locate_Zone( TRACK* start_adresse, wxPoint ref, int layer )
|
|
{
|
|
TRACK* Zone;
|
|
int l_segm;
|
|
|
|
for( Zone = start_adresse; Zone != NULL; Zone = Zone->Next() )
|
|
{
|
|
l_segm = Zone->m_Width >> 1;
|
|
ux0 = Zone->m_Start.x;
|
|
uy0 = Zone->m_Start.y;
|
|
dx = Zone->m_End.x;
|
|
dy = Zone->m_End.y;
|
|
|
|
dx -= ux0;
|
|
dy -= uy0;
|
|
spot_cX = ref.x - ux0;
|
|
spot_cY = ref.y - uy0;
|
|
|
|
if( ( layer != -1 ) && ( Zone->GetLayer() != layer ) )
|
|
continue;
|
|
if( distance( l_segm ) )
|
|
return Zone;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* Location of text on the PCB:
|
|
* INPUT: char pointer to the beginning of the search area
|
|
* Return: pointer to the text description located.
|
|
*/
|
|
TEXTE_PCB* Locate_Texte_Pcb( TEXTE_PCB* pt_txt_pcb, int typeloc )
|
|
{
|
|
int angle;
|
|
EDA_BaseStruct* PtStruct;
|
|
wxPoint ref;
|
|
|
|
SET_REF_POS( ref );
|
|
PtStruct = (EDA_BaseStruct*) pt_txt_pcb;
|
|
for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
|
|
{
|
|
if( PtStruct->Type() != TYPE_TEXTE )
|
|
continue;
|
|
pt_txt_pcb = (TEXTE_PCB*) PtStruct;
|
|
|
|
angle = pt_txt_pcb->m_Orient;
|
|
ux0 = pt_txt_pcb->m_Pos.x;
|
|
uy0 = pt_txt_pcb->m_Pos.y;
|
|
dx = ( pt_txt_pcb->m_Size.x * pt_txt_pcb->GetLength() ) / 2;
|
|
dy = pt_txt_pcb->m_Size.y / 2;
|
|
|
|
dx *= 13;
|
|
dx /= 9; /* Character for factor 13/9. */
|
|
|
|
/* Cursor in the rectangle around the center. */
|
|
spot_cX = ref.x - ux0;
|
|
spot_cY = ref.y - uy0;
|
|
RotatePoint( &spot_cX, &spot_cY, -angle );
|
|
if( ( abs( spot_cX ) <= abs( dx ) ) && ( abs( spot_cY ) <= abs( dy ) ) )
|
|
return pt_txt_pcb;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* Calculate the distance from the cursor to a line segment:
|
|
* (Track, edge, contour module ..
|
|
* Returns:
|
|
* 0 if distance > threshold
|
|
* 1 if distance <= threshold
|
|
* Variables used (must be initialized before use, and
|
|
* are brought to the mark center on the origin of the segment)
|
|
* dx, dy = coord of extremity segment.
|
|
* spot_cX, spot_cY = coord of mouse cursor
|
|
* Search 4 cases:
|
|
* Horizontal segment
|
|
* Vertical segment
|
|
* Segment 45
|
|
* Any segment
|
|
*/
|
|
int distance( int seuil )
|
|
{
|
|
int cXrot, cYrot, segX, segY;
|
|
int pointX, pointY;
|
|
|
|
segX = dx;
|
|
segY = dy;
|
|
pointX = spot_cX;
|
|
pointY = spot_cY;
|
|
|
|
/* Reroute coordinate for the segment in 1st quadrant (coord> = 0). */
|
|
if( segX < 0 ) /* Set > 0 if symmetrical about the axis Y. */
|
|
{
|
|
segX = -segX;
|
|
pointX = -pointX;
|
|
}
|
|
if( segY < 0 ) /* Set > 0 if symmetrical about the axis X. */
|
|
{
|
|
segY = -segY;
|
|
pointY = -pointY;
|
|
}
|
|
|
|
|
|
if( segY == 0 ) /* Horizontal track. */
|
|
{
|
|
if( abs( pointY ) <= seuil )
|
|
{
|
|
if( ( pointX >= 0 ) && ( pointX <= segX ) )
|
|
return 1;
|
|
|
|
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 ) /* Vertical track. */
|
|
{
|
|
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 if( segX == segY ) /* 45 degree track. */
|
|
{
|
|
/* You spin axes of 45 degrees. mouse was then
|
|
* coord: x1 = x * y * cos45 + sin45
|
|
* y1 = y * cos45 - sin45 x *
|
|
* And the segment of track is horizontal.
|
|
* coord recalculation of the mouse (sin45 = cos45 = .707 = 7 / 10
|
|
* Note: sin or cos45 = .707, and when recalculating coord
|
|
* dX45 and dy45, lect coeff .707 is neglected, dx and dy are both
|
|
* actually .707
|
|
* too big. (security hole too small)
|
|
* spot_cX *, Y * must be by .707 * .707 = 0.5
|
|
*/
|
|
|
|
cXrot = (pointX + pointY) >> 1;
|
|
cYrot = (pointY - pointX) >> 1;
|
|
|
|
/* Recalculate coordinates of extremity segment, which will be vertical
|
|
* following the orientation of axes on the screen: DX45 = pointx
|
|
* (or pointy) and 1.414 is actually greater, and dy45 = 0
|
|
*
|
|
* Threshold should be .707 to reflect the difference in coeff dx, dy
|
|
*/
|
|
seuil *= 7; seuil /= 10;
|
|
if( abs( cYrot ) <= seuil )
|
|
{
|
|
if( ( cXrot >= 0 ) && ( cXrot <= segX ) )
|
|
return 1;
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
else /* Any orientation. */
|
|
{
|
|
/* There is a change of axis (rotation), so that the segment
|
|
* track is horizontal in the new reference, */
|
|
int angle;
|
|
|
|
angle = (int) ( atan2( (double) segY, (double) segX ) * 1800 / M_PI);
|
|
cXrot = pointX;
|
|
cYrot = pointY;
|
|
RotatePoint( &cXrot, &cYrot, angle ); /* Rotate test point. */
|
|
RotatePoint( &segX, &segY, angle ); /* Rotate segment. */
|
|
|
|
/* The track is horizontal, following the changes to coordinate
|
|
* axis and, therefore segX = length of segment
|
|
*/
|
|
|
|
if( abs( cYrot ) <= seuil )
|
|
{
|
|
if( ( cXrot >= 0 ) && ( cXrot <= segX ) )
|
|
return 1;
|
|
|
|
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;
|
|
}
|