467 lines
15 KiB
C++
467 lines
15 KiB
C++
/***************************************************/
|
||
/* Localisation des elements pointes par la souris */
|
||
/***************************************************/
|
||
|
||
#include "fctsys.h"
|
||
#include "common.h"
|
||
#include "class_drawpanel.h"
|
||
|
||
#include "pcbnew.h"
|
||
#include "gerbview.h"
|
||
#include "trigo.h"
|
||
#include "protos.h"
|
||
|
||
|
||
/* variables locales */
|
||
int ux0, uy0, dx, dy, spot_cX, spot_cY; /* Variables utilisees pour
|
||
* la localisation des segments */
|
||
/* fonctions locales */
|
||
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 de calcul de la coord de pointage selon le curseur
|
||
* (ON/OFF grille) choisi
|
||
*/
|
||
#define SET_REF_POS( ref ) if( typeloc == CURSEUR_ON_GRILLE ) \
|
||
{ ref = ActiveScreen->m_Curseur; } \
|
||
else { ref = ActiveScreen->m_MousePosition; }
|
||
|
||
|
||
/*************************************************************/
|
||
BOARD_ITEM* WinEDA_GerberFrame::Locate( int typeloc )
|
||
/*************************************************************/
|
||
|
||
/* Fonction de localisation generale
|
||
* Affiche les caract de la stucture localis<69>e et retourne un pointeur
|
||
* sur celle-ci
|
||
*/
|
||
{
|
||
TEXTE_PCB* pt_texte_pcb;
|
||
TRACK* Track, * TrackLocate;
|
||
DRAWSEGMENT* DrawSegm;
|
||
int layer;
|
||
|
||
/* Localistion des pistes et vias, avec priorite aux vias */
|
||
layer = GetScreen()->m_Active_Layer;
|
||
Track = Locate_Pistes( GetBoard()->m_Track, -1, typeloc );
|
||
if( Track != NULL )
|
||
{
|
||
TrackLocate = Track; /* Reperage d'une piste ou via */
|
||
/* recherche de 1 via eventuelle */
|
||
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 ) // texte type PCB localise
|
||
{
|
||
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;
|
||
}
|
||
|
||
|
||
/********************************************************/
|
||
DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int typeloc )
|
||
/********************************************************/
|
||
|
||
/* Localisation de segments de contour du type edge pcb ou draw
|
||
* (selon couche active)
|
||
* Retourne:
|
||
* Pointeur sur DEBUT du segment localise
|
||
* NULL si rien trouve
|
||
*/
|
||
{
|
||
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;
|
||
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
|
||
dx = pts->m_End.x - ux0; dy = pts->m_End.y - uy0;
|
||
spot_cX = ref.x - ux0; spot_cY = ref.y - uy0;
|
||
|
||
/* detection : */
|
||
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;
|
||
/* pour un arc, controle complementaire */
|
||
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;
|
||
}
|
||
|
||
|
||
/****************************************************************************/
|
||
/* TRACK *Locate_Pistes(TRACK * start_adresse, int MasqueLayer,int typeloc) */
|
||
/* TRACK *Locate_Pistes(TRACK * start_adresse, wxPoint ref, int MasqueLayer)*/
|
||
/****************************************************************************/
|
||
|
||
/*
|
||
* 1 - routine de localisation du segment de piste pointe par la souris.
|
||
* 2 - routine de localisation du segment de piste pointe par le point
|
||
* ref_pX , ref_pY.r
|
||
*
|
||
* La recherche commence a l'adresse 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; /* pointeur sur les pistes */
|
||
int l_piste; /* demi-largeur de la piste */
|
||
|
||
for( Track = start_adresse; Track != NULL; Track = Track->Next() )
|
||
{
|
||
if( Track->GetState( BUSY | DELETED ) )
|
||
continue;
|
||
/* calcul des coordonnees du segment teste */
|
||
l_piste = Track->m_Width >> 1; /* l_piste = demi largeur piste */
|
||
ux0 = Track->m_Start.x; uy0 = Track->m_Start.y; /* coord de depart */
|
||
dx = Track->m_End.x; dy = Track->m_End.y; /* coord d'arrivee */
|
||
|
||
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
|
||
dx -= ux0; dy -= uy0;
|
||
spot_cX = ref.x - ux0; spot_cY = ref.y - uy0;
|
||
|
||
if( Track->Type() == TYPE_VIA ) /* VIA rencontree */
|
||
{
|
||
if( (abs( spot_cX ) <= l_piste ) && (abs( spot_cY ) <=l_piste) )
|
||
{
|
||
return Track;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if( Layer >= 0 )
|
||
if( Track->GetLayer() != Layer )
|
||
continue;/* Segments sur couches differentes */
|
||
if( distance( l_piste ) )
|
||
return Track;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
/****************************************************************/
|
||
/* TRACK * Locate_Zone(TRACK * start_adresse, int layer, */
|
||
/* int typeloc) */
|
||
/* TRACK * Locate_Zone(TRACK * start_adresse,wxPoint ref, int layer) */
|
||
/****************************************************************/
|
||
|
||
/*
|
||
* 1 - routine de localisation du segment de zone pointe par la souris.
|
||
* 2 - routine de localisation du segment de zone pointe par le point
|
||
* ref_pX , ref_pY.r
|
||
*
|
||
* Si layer == -1 , le tst de la couche n'est pas fait
|
||
*
|
||
* La recherche commence a l'adresse 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 );
|
||
}
|
||
|
||
|
||
TRACK* Locate_Zone( TRACK* start_adresse, wxPoint ref, int layer )
|
||
{
|
||
TRACK* Zone; /* pointeur sur les pistes */
|
||
int l_segm; /* demi-largeur de la piste */
|
||
|
||
for( Zone = start_adresse; Zone != NULL; Zone = Zone->Next() )
|
||
{
|
||
/* calcul des coordonnees du segment teste */
|
||
l_segm = Zone->m_Width >> 1; /* l_piste = demi largeur piste */
|
||
ux0 = Zone->m_Start.x; uy0 = Zone->m_Start.y; /* coord de depart */
|
||
dx = Zone->m_End.x; dy = Zone->m_End.y; /* coord d'arrivee */
|
||
|
||
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
|
||
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;
|
||
}
|
||
|
||
|
||
/***************************************************************/
|
||
/* TEXTE_PCB * Locate_Texte_Pcb(char * pt_txt_pcb,int typeloc) */
|
||
/***************************************************************/
|
||
|
||
/* localisation des inscriptions sur le Pcb:
|
||
* entree : char pointeur sur le debut de la zone de recherche
|
||
* retour : pointeur sur la description du texte localise
|
||
*/
|
||
|
||
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; /* Facteur de forme des lettres : 13/9 */
|
||
|
||
/* la souris est-elle dans ce rectangle autour du centre */
|
||
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;
|
||
}
|
||
|
||
|
||
/*****************************/
|
||
/* int distance(int seuil) */
|
||
/*****************************/
|
||
|
||
/*
|
||
* Calcul de la distance du curseur souris a un segment de droite :
|
||
* ( piste, edge, contour module ..
|
||
* retourne:
|
||
* 0 si distance > seuil
|
||
* 1 si distance <= seuil
|
||
* Variables utilisees ( doivent etre initialisees avant appel , et
|
||
* 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 45
|
||
* segment quelconque
|
||
*/
|
||
|
||
int distance( int seuil )
|
||
{
|
||
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 en >0 par symetrie par rapport a l'axe Y */
|
||
{
|
||
segX = -segX; pointX = -pointX;
|
||
}
|
||
if( segY < 0 ) /* mise en > 0 par symetrie 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 if( segX == segY ) /* piste a 45 degre */
|
||
{
|
||
/* on fait tourner les axes de 45 degre. la souris a alors les
|
||
* coord : x1 = x*cos45 + y*sin45
|
||
* y1 = y*cos45 - x*sin45
|
||
* et le segment de piste est alors horizontal.
|
||
* recalcul des coord de la souris ( sin45 = cos45 = .707 = 7/10
|
||
* remarque : sin ou cos45 = .707, et lors du recalcul des coord
|
||
* dx45 et dy45, lec coeff .707 est neglige, dx et dy sont en fait .707 fois
|
||
* trop grands. (c.a.d trop petits)
|
||
* spot_cX,Y doit etre * par .707 * .707 = 0.5 */
|
||
|
||
cXrot = (pointX + pointY) >> 1;
|
||
cYrot = (pointY - pointX) >> 1;
|
||
|
||
/* recalcul des coord de l'extremite du segment , qui sera vertical
|
||
* suite a l'orientation des axes sur l'ecran : dx45 = pointX (ou pointY)
|
||
* et est en fait 1,414 plus grand , et dy45 = 0 */
|
||
|
||
// seuil doit etre * .707 pour tenir compte du coeff de reduction sur dx,dy
|
||
seuil *= 7; seuil /= 10;
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
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( (double) segY, (double) 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;
|
||
}
|