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