Commit c1e3416a authored by dickelbeck's avatar dickelbeck

searching and beautifying

parent 66080848
...@@ -5,6 +5,20 @@ Please add newer entries at the top, list the date and your name with ...@@ -5,6 +5,20 @@ Please add newer entries at the top, list the date and your name with
email address. email address.
2007-Aug-08 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
+ pcbnew & common
* Renamed locate.cpp's distance() to DistanceTest() and moved it to trigo.cpp.
Pass more parameters to DistanceTest and removed globals that were used by
distance() in locate.cpp.
Moved and renamed DistanceTest function proto from protos.h to trigo.h.
* Implemented HitTest() for class_cotation, class_mire, and a few other classes
by factoring out existing code from locate.cpp. locate.cpp should operate
exactly the same as before.
* Detected that the suspected class_module hit-testing bug was not real,
i.e. no bug found.
2007-aug-08 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> 2007-aug-08 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================ ================================================================================
+ eeschema + eeschema
......
...@@ -9,6 +9,163 @@ ...@@ -9,6 +9,163 @@
#include "trigo.h" #include "trigo.h"
/*****************************/
bool DistanceTest( int seuil, int dx, int dy, int spot_cX, int spot_cY )
/*****************************/
/*
* Calcul de la distance du curseur souris a un segment de droite :
* ( piste, edge, contour module ..
* retourne:
* false si distance > seuil
* true 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 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 true;
}
if( (pointX > segX) && ( pointX <= (segX + seuil) ) )
{
if( ( ( (pointX - segX) * (pointX - segX) ) + (pointY * pointY) ) <=
(seuil * seuil) )
return true;
}
}
}
else if( segX == 0 ) /* piste verticale */
{
if( abs( pointX ) <= seuil )
{
if( (pointY >= 0 ) && (pointY <= segY) )
return true;
if( (pointY < 0) && (pointY >= -seuil) )
{
if( ( (pointY * pointY) + (pointX * pointX) ) <= (seuil * seuil) )
return true;
}
if( (pointY > segY) && ( pointY <= (segY + seuil) ) )
{
if( ( ( (pointY - segY) * (pointY - segY) ) + (pointX * pointX) ) <=
(seuil * seuil) )
return true;
}
}
}
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 true;
/* Etude des extremites : cercle de rayon seuil */
if( (cXrot < 0) && (cXrot >= -seuil) )
{
if( ( (cXrot * cXrot) + (cYrot * cYrot) ) <= (seuil * seuil) )
return true;
}
if( (cXrot > segX) && ( cXrot <= (segX + seuil) ) )
{
if( ( ( (cXrot - segX) * (cXrot - segX) ) + (cYrot * cYrot) ) <= (seuil * seuil) )
return true;
}
}
}
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 true;
/* Etude des extremites : cercle de rayon seuil */
if( (cXrot < 0) && (cXrot >= -seuil) )
{
if( ( (cXrot * cXrot) + (cYrot * cYrot) ) <= (seuil * seuil) )
return true;
}
if( (cXrot > segX) && ( cXrot <= (segX + seuil) ) )
{
if( ( ( (cXrot - segX) * (cXrot - segX) ) + (cYrot * cYrot) ) <= (seuil * seuil) )
return true;
}
}
}
return false;
}
/***********************************/ /***********************************/
int ArcTangente( int dy, int dx ) int ArcTangente( int dy, int dx )
/***********************************/ /***********************************/
...@@ -217,3 +374,5 @@ void RotatePoint( double* pX, double* pY, int angle ) ...@@ -217,3 +374,5 @@ void RotatePoint( double* pX, double* pY, int angle )
*pY = fpy; *pY = fpy;
} }
} }
...@@ -235,7 +235,6 @@ public: ...@@ -235,7 +235,6 @@ public:
#if defined(DEBUG) #if defined(DEBUG)
/** /**
* Function GetClass * Function GetClass
* returns the class name. * returns the class name.
...@@ -264,7 +263,7 @@ public: ...@@ -264,7 +263,7 @@ public:
* @param typeloc * @param typeloc
* @return EDA_BaseStruct* - if a direct hit, else NULL. * @return EDA_BaseStruct* - if a direct hit, else NULL.
*/ */
EDA_BaseStruct* FindPadOrModule( const wxPoint& refPos, int layer, int typeloc ); EDA_BaseStruct* FindPadOrModule( const wxPoint& refPos, int layer );
#endif #endif
}; };
...@@ -322,6 +321,27 @@ public: ...@@ -322,6 +321,27 @@ public:
void UnLink( void ); void UnLink( void );
void Copy( DRAWSEGMENT* source ); void Copy( DRAWSEGMENT* source );
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param ref_pos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool HitTest( const wxPoint& ref_pos );
#if defined(DEBUG)
/**
* Function GetClass
* returns the class name.
* @return wxString
*/
wxString GetClass() const
{
return wxT("pgraphic");
}
#endif
}; };
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#define TRIGO_H #define TRIGO_H
/* Prototype des fonctions de TRIGO.CC */ /* Prototype des fonctions de trigo.cpp */
void RotatePoint(int *pX, int *pY, int angle); void RotatePoint(int *pX, int *pY, int angle);
void RotatePoint(int *pX, int *pY, int cx, int cy, int angle); void RotatePoint(int *pX, int *pY, int cx, int cy, int angle);
void RotatePoint(wxPoint *point, const wxPoint & centre, int angle); void RotatePoint(wxPoint *point, const wxPoint & centre, int angle);
...@@ -19,6 +19,7 @@ int ArcTangente(int dy, int dx); ...@@ -19,6 +19,7 @@ int ArcTangente(int dy, int dx);
Analogue a atan2 ( mais plus rapide pour les caculs si Analogue a atan2 ( mais plus rapide pour les caculs si
l'angle est souvent 0, -1800, ou +- 900 */ l'angle est souvent 0, -1800, ou +- 900 */
bool DistanceTest( int seuil, int dx, int dy, int spot_cX, int spot_cY );
......
...@@ -290,75 +290,64 @@ void BOARD::Show( int nestLevel, std::ostream& os ) ...@@ -290,75 +290,64 @@ void BOARD::Show( int nestLevel, std::ostream& os )
// see pcbstruct.h // see pcbstruct.h
EDA_BaseStruct* BOARD::FindPadOrModule( const wxPoint& refPos, int layer, int typeloc ) EDA_BaseStruct* BOARD::FindPadOrModule( const wxPoint& refPos, int layer )
{ {
class PadOrModule : public INSPECTOR class PadOrModule : public INSPECTOR
{ {
public: public:
EDA_BaseStruct* found; EDA_BaseStruct* found;
int layer; int layer;
int typeloc;
PadOrModule( int alayer, int atypeloc ) : PadOrModule( int alayer ) :
found(0), found(0), // found is NULL
layer(alayer), layer(alayer)
typeloc(atypeloc) {} {
}
SEARCH_RESULT Inspect( EDA_BaseStruct* testItem, const void* testData ) SEARCH_RESULT Inspect( EDA_BaseStruct* testItem, const void* testData )
{ {
const wxPoint* refPos = (const wxPoint*) testData; const wxPoint& refPos = *(const wxPoint*) testData;
if( testItem->m_StructType == TYPEMODULE ) if( testItem->m_StructType == TYPEPAD )
{ {
int mlayer = ((MODULE*)testItem)->m_Layer; if( testItem->HitTest( refPos ) )
if( typeloc & MATCH_LAYER )
{
if( layer != mlayer )
return SEARCH_CONTINUE;
}
if( typeloc & VISIBLE_ONLY )
{
if( !IsModuleLayerVisible(mlayer) )
return SEARCH_CONTINUE;
}
if( testItem->HitTest( *refPos ) )
{ {
found = testItem; found = testItem;
return SEARCH_QUIT; return SEARCH_QUIT;
} }
} }
else if( testItem->m_StructType == TYPEPAD )
else if( testItem->m_StructType == TYPEMODULE )
{ {
if( testItem->HitTest( *refPos ) ) int mlayer = ((MODULE*)testItem)->m_Layer;
// consider only visible modules
if( IsModuleLayerVisible( mlayer ) )
{ {
found = testItem; if( testItem->HitTest( refPos ) )
return SEARCH_QUIT; {
// save regardless of layer test, but only quit if
// layer matches, otherwise use this item if no future
// layer match.
found = testItem;
if( layer == mlayer )
return SEARCH_QUIT;
}
} }
} }
else { int debug=1; /* this should not happen, because of scanTypes */ }
return SEARCH_CONTINUE; return SEARCH_CONTINUE;
} }
}; };
PadOrModule inspector1( layer, MATCH_LAYER ); PadOrModule inspector( layer );
PadOrModule inspector2( layer, VISIBLE_ONLY );
// search only for PADs first, then MODULES, and preferably a layer match
static const KICAD_T scanTypes[] = { TYPEPAD, TYPEMODULE, EOT }; static const KICAD_T scanTypes[] = { TYPEPAD, TYPEMODULE, EOT };
// search the current layer first IterateForward( m_Modules, &inspector, &refPos, scanTypes );
if( SEARCH_QUIT == IterateForward( m_Modules, &inspector1, &refPos, scanTypes ) )
return inspector1.found;
// if not found, set layer to don't care and search again
if( SEARCH_QUIT == IterateForward( m_Modules, &inspector2, &refPos, scanTypes ) )
return inspector2.found;
return NULL; return inspector.found;
} }
#endif #endif
...@@ -7,348 +7,476 @@ ...@@ -7,348 +7,476 @@
#include "common.h" #include "common.h"
#include "pcbnew.h" #include "pcbnew.h"
#include "trigo.h"
COTATION::COTATION( EDA_BaseStruct* StructFather ) :
EDA_BaseStruct( StructFather, TYPECOTATION )
COTATION::COTATION(EDA_BaseStruct * StructFather):
EDA_BaseStruct( StructFather, TYPECOTATION)
{ {
m_Layer = DRAW_LAYER; m_Layer = DRAW_LAYER;
m_Width = 50; m_Width = 50;
m_Value = 0; m_Value = 0;
m_Shape = 0; m_Shape = 0;
m_Unit = INCHES; m_Unit = INCHES;
m_Text = new TEXTE_PCB(this); m_Text = new TEXTE_PCB( this );
} }
/* Effacement memoire de la structure */ /* Effacement memoire de la structure */
COTATION::~COTATION(void) COTATION::~COTATION( void )
{ {
delete m_Text; delete m_Text;
} }
/* supprime du chainage la structure Struct /* supprime du chainage la structure Struct
les structures arrieres et avant sont chainees directement * les structures arrieres et avant sont chainees directement
*/ */
void COTATION::UnLink( void ) void COTATION::UnLink( void )
{ {
/* Modification du chainage arriere */ /* Modification du chainage arriere */
if( Pback ) if( Pback )
{ {
if( Pback->m_StructType != TYPEPCB) if( Pback->m_StructType != TYPEPCB )
{ {
Pback->Pnext = Pnext; Pback->Pnext = Pnext;
} }
else /* Le chainage arriere pointe sur la structure "Pere" */
else /* Le chainage arriere pointe sur la structure "Pere" */ {
{ ( (BOARD*) Pback )->m_Drawings = Pnext;
((BOARD*)Pback)->m_Drawings = Pnext; }
} }
}
/* Modification du chainage avant */
/* Modification du chainage avant */ if( Pnext )
if( Pnext) Pnext->Pback = Pback; Pnext->Pback = Pback;
Pnext = Pback = NULL; Pnext = Pback = NULL;
} }
/* Changement du texte de la cotation */ /* Changement du texte de la cotation */
void COTATION:: SetText(const wxString & NewText) void COTATION:: SetText( const wxString& NewText )
{ {
m_Text->m_Text = NewText; m_Text->m_Text = NewText;
} }
/*************************************/ /*************************************/
void COTATION::Copy(COTATION * source) void COTATION::Copy( COTATION* source )
/*************************************/ /*************************************/
{ {
m_Value = source->m_Value; m_Value = source->m_Value;
m_Layer = source->m_Layer; m_Layer = source->m_Layer;
m_Width = source->m_Width; m_Width = source->m_Width;
m_Pos = source->m_Pos; m_Pos = source->m_Pos;
m_Shape = source->m_Shape; m_Shape = source->m_Shape;
m_Unit = source->m_Unit; m_Unit = source->m_Unit;
m_TimeStamp = GetTimeStamp(); m_TimeStamp = GetTimeStamp();
m_Text->Copy(source->m_Text); m_Text->Copy( source->m_Text );
Barre_ox = source->Barre_ox; Barre_oy = source->Barre_oy; Barre_ox = source->Barre_ox; Barre_oy = source->Barre_oy;
Barre_fx = source->Barre_fx; Barre_fy = source->Barre_fy; Barre_fx = source->Barre_fx; Barre_fy = source->Barre_fy;
TraitG_ox = source->TraitG_ox; TraitG_oy = source->TraitG_oy; TraitG_ox = source->TraitG_ox; TraitG_oy = source->TraitG_oy;
TraitG_fx = source->TraitG_fx; TraitG_fy = source->TraitG_fy; TraitG_fx = source->TraitG_fx; TraitG_fy = source->TraitG_fy;
TraitD_ox = source->TraitD_ox; TraitD_oy = source->TraitD_oy; TraitD_ox = source->TraitD_ox; TraitD_oy = source->TraitD_oy;
TraitD_fx = source->TraitD_fx; TraitD_fy = source->TraitD_fy; TraitD_fx = source->TraitD_fx; TraitD_fy = source->TraitD_fy;
FlecheD1_ox = source->FlecheD1_ox; FlecheD1_oy = source->FlecheD1_oy; FlecheD1_ox = source->FlecheD1_ox; FlecheD1_oy = source->FlecheD1_oy;
FlecheD1_fx = source->FlecheD1_fx; FlecheD1_fy = source->FlecheD1_fy; FlecheD1_fx = source->FlecheD1_fx; FlecheD1_fy = source->FlecheD1_fy;
FlecheD2_ox = source->FlecheD2_ox; FlecheD2_oy = source->FlecheD2_oy; FlecheD2_ox = source->FlecheD2_ox; FlecheD2_oy = source->FlecheD2_oy;
FlecheD2_fx = source->FlecheD2_fx; FlecheD2_fy = source->FlecheD2_fy; FlecheD2_fx = source->FlecheD2_fx; FlecheD2_fy = source->FlecheD2_fy;
FlecheG1_ox = source->FlecheG1_ox; FlecheG1_oy = source->FlecheG1_oy; FlecheG1_ox = source->FlecheG1_ox; FlecheG1_oy = source->FlecheG1_oy;
FlecheG1_fx = source->FlecheG1_fx; FlecheG1_fy = source->FlecheG1_fy; FlecheG1_fx = source->FlecheG1_fx; FlecheG1_fy = source->FlecheG1_fy;
FlecheG2_ox = source->FlecheG2_ox; FlecheG2_oy = source->FlecheG2_oy; FlecheG2_ox = source->FlecheG2_ox; FlecheG2_oy = source->FlecheG2_oy;
FlecheG2_fx = source->FlecheG2_fx; FlecheG2_fy = source->FlecheG2_fy; FlecheG2_fx = source->FlecheG2_fx; FlecheG2_fy = source->FlecheG2_fy;
} }
/***************************************************************/ /***************************************************************/
bool COTATION::ReadCotationDescr(FILE * File, int * LineNum) bool COTATION::ReadCotationDescr( FILE* File, int* LineNum )
/***************************************************************/ /***************************************************************/
{ {
char Line[2048], Text[2048]; char Line[2048], Text[2048];
while( GetLine(File, Line, LineNum ) != NULL ) while( GetLine( File, Line, LineNum ) != NULL )
{ {
if(strnicmp(Line,"$EndCOTATION",4) == 0) return TRUE; if( strnicmp( Line, "$EndCOTATION", 4 ) == 0 )
return TRUE;
if(Line[0] == 'V')
{ if( Line[0] == 'V' )
sscanf( Line+2," %d",&m_Value); {
continue; sscanf( Line + 2, " %d", &m_Value );
} continue;
}
if(Line[0] == 'G')
{ if( Line[0] == 'G' )
sscanf( Line+2," %d %d %lX",&m_Shape, &m_Layer, &m_TimeStamp); {
sscanf( Line + 2, " %d %d %lX", &m_Shape, &m_Layer, &m_TimeStamp );
/* Mise a jour des param .layer des sous structures */
if ( m_Layer < FIRST_NO_COPPER_LAYER ) /* Mise a jour des param .layer des sous structures */
m_Layer = FIRST_NO_COPPER_LAYER; if( m_Layer < FIRST_NO_COPPER_LAYER )
if ( m_Layer > LAST_NO_COPPER_LAYER ) m_Layer = FIRST_NO_COPPER_LAYER;
m_Layer = LAST_NO_COPPER_LAYER; if( m_Layer > LAST_NO_COPPER_LAYER )
m_Layer = LAST_NO_COPPER_LAYER;
m_Text->m_Layer = m_Layer;
continue; m_Text->m_Layer = m_Layer;
} continue;
}
if(Line[0] == 'T')
{ if( Line[0] == 'T' )
ReadDelimitedText(Text, Line+2, sizeof(Text) ); {
m_Text->m_Text = CONV_FROM_UTF8(Text); ReadDelimitedText( Text, Line + 2, sizeof(Text) );
continue; m_Text->m_Text = CONV_FROM_UTF8( Text );
} continue;
}
if(Line[0] == 'P')
{ if( Line[0] == 'P' )
sscanf( Line+2," %d %d %d %d %d %d %d", {
&m_Text->m_Pos.x, &m_Text->m_Pos.y, sscanf( Line + 2, " %d %d %d %d %d %d %d",
&m_Text->m_Size.x, &m_Text->m_Size.y, &m_Text->m_Pos.x, &m_Text->m_Pos.y,
&m_Text->m_Width,&m_Text->m_Orient, &m_Text->m_Size.x, &m_Text->m_Size.y,
&m_Text->m_Miroir); &m_Text->m_Width, &m_Text->m_Orient,
&m_Text->m_Miroir );
m_Pos = m_Text->m_Pos;
continue; m_Pos = m_Text->m_Pos;
} continue;
}
if( Line[0] == 'S')
{ if( Line[0] == 'S' )
switch( Line[1] ) {
{ switch( Line[1] )
int Dummy; {
case 'b' : int Dummy;
sscanf( Line+2," %d %d %d %d %d %d",
&Dummy, case 'b':
&Barre_ox, &Barre_oy, sscanf( Line + 2, " %d %d %d %d %d %d",
&Barre_fx, &Barre_fy, &Dummy,
&m_Width ); &Barre_ox, &Barre_oy,
break; &Barre_fx, &Barre_fy,
&m_Width );
case 'd': break;
sscanf( Line+2," %d %d %d %d %d %d",
&Dummy, case 'd':
&TraitD_ox, &TraitD_oy, sscanf( Line + 2, " %d %d %d %d %d %d",
&TraitD_fx, &TraitD_fy, &Dummy,
&Dummy ); &TraitD_ox, &TraitD_oy,
break; &TraitD_fx, &TraitD_fy,
&Dummy );
case 'g': break;
sscanf( Line+2," %d %d %d %d %d %d",
&Dummy, case 'g':
&TraitG_ox, &TraitG_oy, sscanf( Line + 2, " %d %d %d %d %d %d",
&TraitG_fx, &TraitG_fy, &Dummy,
&Dummy ); &TraitG_ox, &TraitG_oy,
break; &TraitG_fx, &TraitG_fy,
&Dummy );
case '1': break;
sscanf( Line+2," %d %d %d %d %d %d",
&Dummy, case '1':
&FlecheD1_ox, &FlecheD1_oy, sscanf( Line + 2, " %d %d %d %d %d %d",
&FlecheD1_fx, &FlecheD1_fy, &Dummy,
&Dummy ); &FlecheD1_ox, &FlecheD1_oy,
break; &FlecheD1_fx, &FlecheD1_fy,
&Dummy );
case '2': break;
sscanf( Line+2," %d %d %d %d %d %d",
&Dummy, case '2':
&FlecheD2_ox, &FlecheD2_oy, sscanf( Line + 2, " %d %d %d %d %d %d",
&FlecheD2_fx, &FlecheD2_fy, &Dummy,
&Dummy ); &FlecheD2_ox, &FlecheD2_oy,
break; &FlecheD2_fx, &FlecheD2_fy,
&Dummy );
case '3': break;
sscanf( Line+2," %d %d %d %d %d %d\n",
&Dummy, case '3':
&FlecheG1_ox, &FlecheG1_oy, sscanf( Line + 2, " %d %d %d %d %d %d\n",
&FlecheG1_fx, &FlecheG1_fy, &Dummy,
&Dummy); &FlecheG1_ox, &FlecheG1_oy,
break; &FlecheG1_fx, &FlecheG1_fy,
&Dummy );
case '4': break;
sscanf( Line+2," %d %d %d %d %d %d",
&Dummy, case '4':
&FlecheG2_ox, &FlecheG2_oy, sscanf( Line + 2, " %d %d %d %d %d %d",
&FlecheG2_fx, &FlecheG2_fy, &Dummy,
&Dummy ); &FlecheG2_ox, &FlecheG2_oy,
break; &FlecheG2_fx, &FlecheG2_fy,
} &Dummy );
break;
continue; }
}
} continue;
return FALSE; }
}
return FALSE;
} }
/**************************************************/ /**************************************************/
bool COTATION::WriteCotationDescr(FILE * File) bool COTATION::WriteCotationDescr( FILE* File )
/**************************************************/ /**************************************************/
{ {
if( GetState(DELETED) ) return FALSE; if( GetState( DELETED ) )
return FALSE;
fprintf( File, "$COTATION\n"); fprintf( File, "$COTATION\n" );
fprintf( File,"Ge %d %d %lX\n",m_Shape, fprintf( File, "Ge %d %d %lX\n", m_Shape,
m_Layer, m_TimeStamp); m_Layer, m_TimeStamp );
fprintf( File,"Va %d\n",m_Value); fprintf( File, "Va %d\n", m_Value );
if( ! m_Text->m_Text.IsEmpty() ) if( !m_Text->m_Text.IsEmpty() )
fprintf( File,"Te \"%s\"\n",CONV_TO_UTF8(m_Text->m_Text)); fprintf( File, "Te \"%s\"\n", CONV_TO_UTF8( m_Text->m_Text ) );
else fprintf( File,"Te \"?\"\n"); else
fprintf( File, "Te \"?\"\n" );
fprintf( File,"Po %d %d %d %d %d %d %d\n", fprintf( File, "Po %d %d %d %d %d %d %d\n",
m_Text->m_Pos.x, m_Text->m_Pos.y, m_Text->m_Pos.x, m_Text->m_Pos.y,
m_Text->m_Size.x, m_Text->m_Size.y, m_Text->m_Size.x, m_Text->m_Size.y,
m_Text->m_Width,m_Text->m_Orient, m_Text->m_Width, m_Text->m_Orient,
m_Text->m_Miroir); m_Text->m_Miroir );
fprintf( File,"Sb %d %d %d %d %d %d\n",S_SEGMENT, fprintf( File, "Sb %d %d %d %d %d %d\n", S_SEGMENT,
Barre_ox, Barre_oy, Barre_ox, Barre_oy,
Barre_fx, Barre_fy, m_Width ); Barre_fx, Barre_fy, m_Width );
fprintf( File,"Sd %d %d %d %d %d %d\n",S_SEGMENT, fprintf( File, "Sd %d %d %d %d %d %d\n", S_SEGMENT,
TraitD_ox, TraitD_oy, TraitD_ox, TraitD_oy,
TraitD_fx, TraitD_fy, m_Width ); TraitD_fx, TraitD_fy, m_Width );
fprintf( File,"Sg %d %d %d %d %d %d\n",S_SEGMENT, fprintf( File, "Sg %d %d %d %d %d %d\n", S_SEGMENT,
TraitG_ox, TraitG_oy, TraitG_ox, TraitG_oy,
TraitG_fx, TraitG_fy, m_Width ); TraitG_fx, TraitG_fy, m_Width );
fprintf( File,"S1 %d %d %d %d %d %d\n",S_SEGMENT, fprintf( File, "S1 %d %d %d %d %d %d\n", S_SEGMENT,
FlecheD1_ox, FlecheD1_oy, FlecheD1_ox, FlecheD1_oy,
FlecheD1_fx, FlecheD1_fy, m_Width ); FlecheD1_fx, FlecheD1_fy, m_Width );
fprintf( File,"S2 %d %d %d %d %d %d\n",S_SEGMENT, fprintf( File, "S2 %d %d %d %d %d %d\n", S_SEGMENT,
FlecheD2_ox, FlecheD2_oy, FlecheD2_ox, FlecheD2_oy,
FlecheD2_fx, FlecheD2_fy, m_Width ); FlecheD2_fx, FlecheD2_fy, m_Width );
fprintf( File,"S3 %d %d %d %d %d %d\n",S_SEGMENT, fprintf( File, "S3 %d %d %d %d %d %d\n", S_SEGMENT,
FlecheG1_ox, FlecheG1_oy, FlecheG1_ox, FlecheG1_oy,
FlecheG1_fx, FlecheG1_fy, m_Width ); FlecheG1_fx, FlecheG1_fy, m_Width );
fprintf( File,"S4 %d %d %d %d %d %d\n",S_SEGMENT, fprintf( File, "S4 %d %d %d %d %d %d\n", S_SEGMENT,
FlecheG2_ox, FlecheG2_oy, FlecheG2_ox, FlecheG2_oy,
FlecheG2_fx, FlecheG2_fy, m_Width ); FlecheG2_fx, FlecheG2_fy, m_Width );
fprintf( File, "$EndCOTATION\n"); fprintf( File, "$EndCOTATION\n" );
return(1); return 1;
} }
/************************************************************************/ /************************************************************************/
void COTATION::Draw(WinEDA_DrawPanel * panel , wxDC * DC, void COTATION::Draw( WinEDA_DrawPanel* panel, wxDC* DC,
const wxPoint & offset, int mode_color) const wxPoint& offset, int mode_color )
/************************************************************************/ /************************************************************************/
/* impression de 1 cotation : serie de n segments + 1 texte /* impression de 1 cotation : serie de n segments + 1 texte
*/ */
{ {
int ox, oy, typeaff, width, gcolor; int ox, oy, typeaff, width, gcolor;
int zoom = panel->GetScreen()->GetZoom(); int zoom = panel->GetScreen()->GetZoom();
ox = offset.x; ox = offset.x;
oy = offset.y; oy = offset.y;
m_Text->Draw(panel, DC, offset, mode_color ); m_Text->Draw( panel, DC, offset, mode_color );
gcolor = g_DesignSettings.m_LayerColor[m_Layer]; gcolor = g_DesignSettings.m_LayerColor[m_Layer];
if( (gcolor & ITEM_NOT_SHOW) != 0 ) return ; if( (gcolor & ITEM_NOT_SHOW) != 0 )
return;
GRSetDrawMode(DC, mode_color);
typeaff = DisplayOpt.DisplayDrawItems; GRSetDrawMode( DC, mode_color );
width = m_Width; typeaff = DisplayOpt.DisplayDrawItems;
if( width/zoom < 2 ) typeaff = FILAIRE;
width = m_Width;
switch( typeaff ) if( width / zoom < 2 )
{ typeaff = FILAIRE;
case FILAIRE:
width = 0; switch( typeaff )
case FILLED: {
GRLine(&panel->m_ClipBox, DC, case FILAIRE:
Barre_ox - ox, Barre_oy - oy, width = 0;
Barre_fx - ox, Barre_fy- oy, width, gcolor);
GRLine(&panel->m_ClipBox, DC, case FILLED:
TraitG_ox - ox, TraitG_oy - oy, GRLine( &panel->m_ClipBox, DC,
TraitG_fx - ox, TraitG_fy- oy, width, gcolor); Barre_ox - ox, Barre_oy - oy,
GRLine(&panel->m_ClipBox, DC, Barre_fx - ox, Barre_fy - oy, width, gcolor );
TraitD_ox - ox, TraitD_oy - oy, GRLine( &panel->m_ClipBox, DC,
TraitD_fx - ox, TraitD_fy- oy, width, gcolor); TraitG_ox - ox, TraitG_oy - oy,
GRLine(&panel->m_ClipBox, DC, TraitG_fx - ox, TraitG_fy - oy, width, gcolor );
FlecheD1_ox - ox, FlecheD1_oy - oy, GRLine( &panel->m_ClipBox, DC,
FlecheD1_fx - ox, FlecheD1_fy- oy, width, gcolor); TraitD_ox - ox, TraitD_oy - oy,
GRLine(&panel->m_ClipBox, DC, TraitD_fx - ox, TraitD_fy - oy, width, gcolor );
FlecheD2_ox - ox, FlecheD2_oy - oy, GRLine( &panel->m_ClipBox, DC,
FlecheD2_fx - ox, FlecheD2_fy- oy, width, gcolor); FlecheD1_ox - ox, FlecheD1_oy - oy,
GRLine(&panel->m_ClipBox, DC, FlecheD1_fx - ox, FlecheD1_fy - oy, width, gcolor );
FlecheG1_ox - ox, FlecheG1_oy - oy, GRLine( &panel->m_ClipBox, DC,
FlecheG1_fx - ox, FlecheG1_fy- oy, width, gcolor); FlecheD2_ox - ox, FlecheD2_oy - oy,
GRLine(&panel->m_ClipBox, DC, FlecheD2_fx - ox, FlecheD2_fy - oy, width, gcolor );
FlecheG2_ox - ox, FlecheG2_oy - oy, GRLine( &panel->m_ClipBox, DC,
FlecheG2_fx - ox, FlecheG2_fy- oy, width, gcolor); FlecheG1_ox - ox, FlecheG1_oy - oy,
break; FlecheG1_fx - ox, FlecheG1_fy - oy, width, gcolor );
GRLine( &panel->m_ClipBox, DC,
case SKETCH: FlecheG2_ox - ox, FlecheG2_oy - oy,
GRCSegm(&panel->m_ClipBox, DC, FlecheG2_fx - ox, FlecheG2_fy - oy, width, gcolor );
Barre_ox - ox, Barre_oy - oy, break;
Barre_fx - ox, Barre_fy- oy,
width, gcolor); case SKETCH:
GRCSegm(&panel->m_ClipBox, DC, GRCSegm( &panel->m_ClipBox, DC,
TraitG_ox - ox, TraitG_oy - oy, Barre_ox - ox, Barre_oy - oy,
TraitG_fx - ox, TraitG_fy- oy, Barre_fx - ox, Barre_fy - oy,
width, gcolor); width, gcolor );
GRCSegm(&panel->m_ClipBox, DC, GRCSegm( &panel->m_ClipBox, DC,
TraitD_ox - ox, TraitD_oy - oy, TraitG_ox - ox, TraitG_oy - oy,
TraitD_fx - ox, TraitD_fy- oy, TraitG_fx - ox, TraitG_fy - oy,
width, gcolor); width, gcolor );
GRCSegm(&panel->m_ClipBox, DC, GRCSegm( &panel->m_ClipBox, DC,
FlecheD1_ox - ox, FlecheD1_oy - oy, TraitD_ox - ox, TraitD_oy - oy,
FlecheD1_fx - ox, FlecheD1_fy- oy, TraitD_fx - ox, TraitD_fy - oy,
width, gcolor); width, gcolor );
GRCSegm(&panel->m_ClipBox, DC, GRCSegm( &panel->m_ClipBox, DC,
FlecheD2_ox - ox, FlecheD2_oy - oy, FlecheD1_ox - ox, FlecheD1_oy - oy,
FlecheD2_fx - ox, FlecheD2_fy- oy, FlecheD1_fx - ox, FlecheD1_fy - oy,
width, gcolor); width, gcolor );
GRCSegm(&panel->m_ClipBox, DC, GRCSegm( &panel->m_ClipBox, DC,
FlecheG1_ox - ox, FlecheG1_oy - oy, FlecheD2_ox - ox, FlecheD2_oy - oy,
FlecheG1_fx - ox, FlecheG1_fy- oy, FlecheD2_fx - ox, FlecheD2_fy - oy,
width, gcolor); width, gcolor );
GRCSegm(&panel->m_ClipBox, DC, GRCSegm( &panel->m_ClipBox, DC,
FlecheG2_ox - ox, FlecheG2_oy - oy, FlecheG1_ox - ox, FlecheG1_oy - oy,
FlecheG2_fx - ox, FlecheG2_fy - oy, FlecheG1_fx - ox, FlecheG1_fy - oy,
width, gcolor); width, gcolor );
break; GRCSegm( &panel->m_ClipBox, DC,
} FlecheG2_ox - ox, FlecheG2_oy - oy,
FlecheG2_fx - ox, FlecheG2_fy - oy,
width, gcolor );
break;
}
} }
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param ref_pos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool COTATION::HitTest( const wxPoint& ref_pos )
{
int ux0, uy0;
int dx, dy, spot_cX, spot_cY;
if( m_Text )
{
// because HitTest() is present in both base classes of TEXTE_PCB
// use a clarifying cast to tell compiler which HitTest()
// to call.
if( static_cast<EDA_TextStruct*>(m_Text)->HitTest( ref_pos ) )
return true;
}
/* Localisation des SEGMENTS ?) */
ux0 = Barre_ox;
uy0 = Barre_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = Barre_fx - ux0;
dy = Barre_fy - uy0;
spot_cX = ref_pos.x - ux0;
spot_cY = ref_pos.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
return true;
ux0 = TraitG_ox;
uy0 = TraitG_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = TraitG_fx - ux0;
dy = TraitG_fy - uy0;
spot_cX = ref_pos.x - ux0;
spot_cY = ref_pos.y - uy0;
/* detection : */
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
return true;
ux0 = TraitD_ox;
uy0 = TraitD_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = TraitD_fx - ux0;
dy = TraitD_fy - uy0;
spot_cX = ref_pos.x - ux0;
spot_cY = ref_pos.y - uy0;
/* detection : */
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
return true;
ux0 = FlecheD1_ox;
uy0 = FlecheD1_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = FlecheD1_fx - ux0;
dy = FlecheD1_fy - uy0;
spot_cX = ref_pos.x - ux0;
spot_cY = ref_pos.y - uy0;
/* detection : */
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
return true;
ux0 = FlecheD2_ox;
uy0 = FlecheD2_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = FlecheD2_fx - ux0;
dy = FlecheD2_fy - uy0;
spot_cX = ref_pos.x - ux0;
spot_cY = ref_pos.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
return true;
ux0 = FlecheG1_ox;
uy0 = FlecheG1_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = FlecheG1_fx - ux0;
dy = FlecheG1_fy - uy0;
spot_cX = ref_pos.x - ux0;
spot_cY = ref_pos.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
return true;
ux0 = FlecheG2_ox;
uy0 = FlecheG2_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = FlecheG2_fx - ux0;
dy = FlecheG2_fy - uy0;
spot_cX = ref_pos.x - ux0;
spot_cY = ref_pos.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
return true;
return false;
}
...@@ -6,42 +6,62 @@ ...@@ -6,42 +6,62 @@
#include "base_struct.h" #include "base_struct.h"
class COTATION: public EDA_BaseStruct class COTATION : public EDA_BaseStruct
{ {
public: public:
int m_Layer; // 0.. 32 ( NON bit a bit) int m_Layer; // 0.. 32 ( NON bit a bit)
int m_Width; int m_Width;
wxPoint m_Pos; wxPoint m_Pos;
int m_Shape; int m_Shape;
int m_Unit; /* 0 = inches, 1 = mm */ int m_Unit; /* 0 = inches, 1 = mm */
int m_Value; /* valeur en unites PCB de la cote */ int m_Value; /* valeur en unites PCB de la cote */
TEXTE_PCB * m_Text; /* pour affichage du texte */ TEXTE_PCB* m_Text; /* pour affichage du texte */
int Barre_ox, Barre_oy, Barre_fx, Barre_fy; int Barre_ox, Barre_oy, Barre_fx, Barre_fy;
int TraitG_ox, TraitG_oy, TraitG_fx, TraitG_fy; int TraitG_ox, TraitG_oy, TraitG_fx, TraitG_fy;
int TraitD_ox, TraitD_oy, TraitD_fx, TraitD_fy; int TraitD_ox, TraitD_oy, TraitD_fx, TraitD_fy;
int FlecheD1_ox, FlecheD1_oy, FlecheD1_fx, FlecheD1_fy; int FlecheD1_ox, FlecheD1_oy, FlecheD1_fx, FlecheD1_fy;
int FlecheD2_ox, FlecheD2_oy, FlecheD2_fx, FlecheD2_fy; int FlecheD2_ox, FlecheD2_oy, FlecheD2_fx, FlecheD2_fy;
int FlecheG1_ox, FlecheG1_oy, FlecheG1_fx, FlecheG1_fy; int FlecheG1_ox, FlecheG1_oy, FlecheG1_fx, FlecheG1_fy;
int FlecheG2_ox, FlecheG2_oy, FlecheG2_fx, FlecheG2_fy; int FlecheG2_ox, FlecheG2_oy, FlecheG2_fx, FlecheG2_fy;
public: public:
COTATION(EDA_BaseStruct * StructFather); COTATION( EDA_BaseStruct* StructFather );
~COTATION(void); ~COTATION( void );
bool ReadCotationDescr(FILE * File, int * LineNum); bool ReadCotationDescr( FILE* File, int* LineNum );
bool WriteCotationDescr(FILE * File); bool WriteCotationDescr( FILE* File );
/* supprime du chainage la structure Struct */ /* supprime du chainage la structure Struct */
void UnLink( void ); void UnLink( void );
/* Modification du texte de la cotation */ /* Modification du texte de la cotation */
void SetText(const wxString & NewText); void SetText( const wxString& NewText );
void Copy(COTATION * source); void Copy( COTATION* source );
void Draw(WinEDA_DrawPanel * panel, wxDC * DC, const wxPoint & offset, int mode_color); void Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& offset, int mode_color );
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param ref_pos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool HitTest( const wxPoint& ref_pos );
#if defined(DEBUG)
/**
* Function GetClass
* returns the class name.
* @return wxString
*/
wxString GetClass() const
{
return wxT( "DIMENSION" );
}
#endif
}; };
#endif // #define COTATION_H #endif // #define COTATION_H
...@@ -438,6 +438,73 @@ int EDGE_MODULE::ReadDescr( char* Line, FILE* File, ...@@ -438,6 +438,73 @@ int EDGE_MODULE::ReadDescr( char* Line, FILE* File,
} }
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param refPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool EDGE_MODULE::HitTest( const wxPoint& ref_pos )
{
int uxf, uyf;
int rayon, dist;
int dx, dy, spot_cX, spot_cY;
int ux0, uy0;
ux0 = m_Start.x;
uy0 = m_Start.y;
uxf = m_End.x;
uyf = m_End.y;
switch( m_Shape )
{
case S_SEGMENT:
/* recalcul des coordonnees avec ux0,uy0 = origine des coord. */
spot_cX = ref_pos.x - ux0;
spot_cY = ref_pos.y - uy0;
dx = uxf - ux0;
dy = uyf - uy0;
if( DistanceTest( m_Width/2, dx, dy, spot_cX, spot_cY ) )
return true;
break;
case S_CIRCLE:
rayon = (int) hypot( (double) (uxf - ux0), (double) (uyf - uy0) );
dist = (int) hypot( (double) (ref_pos.x - ux0), (double) (ref_pos.y - uy0) );
if( abs( rayon - dist ) <= m_Width )
return true;
break;
case S_ARC:
rayon = (int) hypot( (double) (uxf - ux0), (double) (uyf - uy0) );
dist = (int) hypot( (double) (ref_pos.x - ux0), (double) (ref_pos.y - uy0) );
if( abs( rayon - dist ) > m_Width )
break;
/* pour un arc, controle complementaire */
int mouseAngle = (int) ArcTangente( ref_pos.y - uy0, ref_pos.x - ux0 );
int stAngle = (int) ArcTangente( uyf - uy0, uxf - ux0 );
int endAngle = stAngle + m_Angle;
if( endAngle > 3600 )
{
stAngle -= 3600;
endAngle -= 3600;
}
if( (mouseAngle >= stAngle) && (mouseAngle <= endAngle) )
return true;
break;
}
return false; // an unknown m_Shape also returns false
}
#if defined(DEBUG) #if defined(DEBUG)
/** /**
* Function Show * Function Show
......
...@@ -41,6 +41,14 @@ public: ...@@ -41,6 +41,14 @@ public:
void Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& offset, void Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& offset,
int draw_mode ); int draw_mode );
void Draw3D( Pcb3D_GLCanvas* glcanvas ); void Draw3D( Pcb3D_GLCanvas* glcanvas );
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param refPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool HitTest( const wxPoint& refPos );
#if defined(DEBUG) #if defined(DEBUG)
/** /**
...@@ -50,7 +58,7 @@ public: ...@@ -50,7 +58,7 @@ public:
*/ */
virtual wxString GetClass() const virtual wxString GetClass() const
{ {
return wxT( "GRAPHIC" ); return wxT( "MGRAPHIC" );
// return wxT( "EDGE" ); ? // return wxT( "EDGE" ); ?
} }
......
...@@ -9,15 +9,15 @@ ...@@ -9,15 +9,15 @@
#include "pcbnew.h" #include "pcbnew.h"
MIREPCB::MIREPCB( EDA_BaseStruct* StructFather ) :
MIREPCB::MIREPCB(EDA_BaseStruct * StructFather): EDA_BaseStruct( StructFather, TYPEMIRE )
EDA_BaseStruct( StructFather, TYPEMIRE)
{ {
m_Shape = 0; m_Shape = 0;
m_Size = 5000; m_Size = 5000;
} }
MIREPCB::~MIREPCB(void)
MIREPCB::~MIREPCB( void )
{ {
} }
...@@ -25,161 +25,186 @@ MIREPCB::~MIREPCB(void) ...@@ -25,161 +25,186 @@ MIREPCB::~MIREPCB(void)
/***************************/ /***************************/
void MIREPCB::UnLink( void ) void MIREPCB::UnLink( void )
/***************************/ /***************************/
/* supprime du chainage la structure Struct /* supprime du chainage la structure Struct
les structures arrieres et avant sont chainees directement * les structures arrieres et avant sont chainees directement
*/ */
{ {
/* Modification du chainage arriere */ /* Modification du chainage arriere */
if( Pback ) if( Pback )
{ {
if( Pback->m_StructType != TYPEPCB) if( Pback->m_StructType != TYPEPCB )
{ {
Pback->Pnext = Pnext; Pback->Pnext = Pnext;
} }
else /* Le chainage arriere pointe sur la structure "Pere" */
else /* Le chainage arriere pointe sur la structure "Pere" */ {
{ ( (BOARD*) Pback )->m_Drawings = Pnext;
((BOARD*)Pback)->m_Drawings = Pnext; }
} }
}
/* Modification du chainage avant */
/* Modification du chainage avant */ if( Pnext )
if( Pnext) Pnext->Pback = Pback; Pnext->Pback = Pback;
Pnext = Pback = NULL; Pnext = Pback = NULL;
} }
/**********************************/ /**********************************/
void MIREPCB::Copy(MIREPCB * source) void MIREPCB::Copy( MIREPCB* source )
/**********************************/ /**********************************/
{ {
m_Layer = source->m_Layer; m_Layer = source->m_Layer;
m_Width = source->m_Width; m_Width = source->m_Width;
m_Pos = source->m_Pos; m_Pos = source->m_Pos;
m_Shape = source->m_Shape; m_Shape = source->m_Shape;
m_Size = source->m_Size; m_Size = source->m_Size;
m_TimeStamp = GetTimeStamp(); m_TimeStamp = GetTimeStamp();
} }
/**************************************************************/ /**************************************************************/
bool MIREPCB::ReadMirePcbDescr(FILE * File, int * LineNum) bool MIREPCB::ReadMirePcbDescr( FILE* File, int* LineNum )
/**************************************************************/ /**************************************************************/
/* Lecture de la description de 1 segment type Drawing PCB /* Lecture de la description de 1 segment type Drawing PCB
*/ */
{ {
char Line[256]; char Line[256];
while( GetLine(File, Line, LineNum ) != NULL ) while( GetLine( File, Line, LineNum ) != NULL )
{ {
if(strnicmp(Line,"$End",4 ) == 0 ) return TRUE; /* fin de liste */ if( strnicmp( Line, "$End", 4 ) == 0 )
if(Line[0] == 'P') return TRUE; /* fin de liste */
{ if( Line[0] == 'P' )
sscanf( Line+2," %X %d %d %d %d %d %lX", {
&m_Shape, &m_Layer, sscanf( Line + 2, " %X %d %d %d %d %d %lX",
&m_Pos.x, &m_Pos.y, &m_Shape, &m_Layer,
&m_Size, &m_Width, &m_TimeStamp ); &m_Pos.x, &m_Pos.y,
if ( m_Layer < FIRST_NO_COPPER_LAYER ) &m_Size, &m_Width, &m_TimeStamp );
m_Layer = FIRST_NO_COPPER_LAYER; if( m_Layer < FIRST_NO_COPPER_LAYER )
if ( m_Layer > LAST_NO_COPPER_LAYER ) m_Layer = FIRST_NO_COPPER_LAYER;
m_Layer = LAST_NO_COPPER_LAYER; if( m_Layer > LAST_NO_COPPER_LAYER )
m_Layer = LAST_NO_COPPER_LAYER;
} }
} }
return FALSE;
return FALSE;
} }
/************************************************/ /************************************************/
bool MIREPCB::WriteMirePcbDescr(FILE * File) bool MIREPCB::WriteMirePcbDescr( FILE* File )
/************************************************/ /************************************************/
{ {
if( GetState(DELETED) ) return FALSE; if( GetState( DELETED ) )
return FALSE;
fprintf( File, "$MIREPCB\n");
fprintf( File,"Po %X %d %d %d %d %d %8.8lX\n", fprintf( File, "$MIREPCB\n" );
m_Shape, m_Layer, fprintf( File, "Po %X %d %d %d %d %d %8.8lX\n",
m_Pos.x, m_Pos.y, m_Shape, m_Layer,
m_Size, m_Width, m_TimeStamp ); m_Pos.x, m_Pos.y,
fprintf( File, "$EndMIREPCB\n"); m_Size, m_Width, m_TimeStamp );
return TRUE; fprintf( File, "$EndMIREPCB\n" );
return TRUE;
} }
/**********************************************************/ /**********************************************************/
void MIREPCB::Draw(WinEDA_DrawPanel * panel, wxDC * DC, void MIREPCB::Draw( WinEDA_DrawPanel* panel, wxDC* DC,
const wxPoint & offset, int mode_color) const wxPoint& offset, int mode_color )
/**********************************************************/ /**********************************************************/
/* Affichage de 1 mire : 2 segments + 1 cercle /* Affichage de 1 mire : 2 segments + 1 cercle
le cercle a pour rayon le demi rayon de la mire * le cercle a pour rayon le demi rayon de la mire
les 2 traits ont pour longueur le diametre de la mire * les 2 traits ont pour longueur le diametre de la mire
*/ */
{ {
int rayon, ox, oy, gcolor, width; int rayon, ox, oy, gcolor, width;
int dx1,dx2, dy1, dy2; int dx1, dx2, dy1, dy2;
int typeaff; int typeaff;
int zoom; int zoom;
ox = m_Pos.x + offset.x; ox = m_Pos.x + offset.x;
oy = m_Pos.y + offset.y; oy = m_Pos.y + offset.y;
gcolor = g_DesignSettings.m_LayerColor[m_Layer]; gcolor = g_DesignSettings.m_LayerColor[m_Layer];
if ( (gcolor & ITEM_NOT_SHOW) != 0 ) return; if( (gcolor & ITEM_NOT_SHOW) != 0 )
return;
zoom = panel->GetZoom();
zoom = panel->GetZoom();
GRSetDrawMode(DC, mode_color);
typeaff = DisplayOpt.DisplayDrawItems; GRSetDrawMode( DC, mode_color );
width = m_Width; typeaff = DisplayOpt.DisplayDrawItems;
if( width/zoom < 2 ) typeaff = FILAIRE; width = m_Width;
if( width / zoom < 2 )
/* Trace du cercle: */ typeaff = FILAIRE;
rayon = m_Size / 4;
switch( typeaff ) /* Trace du cercle: */
{ rayon = m_Size / 4;
case FILAIRE:
width = 0; switch( typeaff )
case FILLED: {
GRCircle(&panel->m_ClipBox, DC, ox, oy, rayon, width, gcolor); case FILAIRE:
break; width = 0;
case SKETCH: case FILLED:
GRCircle(&panel->m_ClipBox, DC, ox, oy, rayon + (width/2), gcolor) ; GRCircle( &panel->m_ClipBox, DC, ox, oy, rayon, width, gcolor );
GRCircle(&panel->m_ClipBox, DC, ox, oy, rayon - (width/2), gcolor) ; break;
break;
} case SKETCH:
GRCircle( &panel->m_ClipBox, DC, ox, oy, rayon + (width / 2), gcolor );
GRCircle( &panel->m_ClipBox, DC, ox, oy, rayon - (width / 2), gcolor );
/* Trace des 2 traits */ break;
rayon = m_Size/2; }
dx1 = rayon, dy1 = 0;
dx2 = 0, dy2 = rayon;
/* Trace des 2 traits */
if( m_Shape) /* Forme X */ rayon = m_Size / 2;
{ dx1 = rayon, dy1 = 0;
dx1 = dy1 = (rayon * 7)/5; dx2 = 0, dy2 = rayon;
dx2 = dx1; dy2 = -dy1;
} if( m_Shape ) /* Forme X */
{
switch( typeaff ) dx1 = dy1 = (rayon * 7) / 5;
{ dx2 = dx1; dy2 = -dy1;
case FILAIRE: }
case FILLED:
GRLine(&panel->m_ClipBox, DC, ox - dx1, oy - dy1, switch( typeaff )
ox + dx1, oy + dy1, width, gcolor); {
GRLine(&panel->m_ClipBox, DC, ox - dx2, oy - dy2, case FILAIRE:
ox + dx2, oy + dy2, width, gcolor); case FILLED:
break; GRLine( &panel->m_ClipBox, DC, ox - dx1, oy - dy1,
ox + dx1, oy + dy1, width, gcolor );
case SKETCH: GRLine( &panel->m_ClipBox, DC, ox - dx2, oy - dy2,
GRCSegm(&panel->m_ClipBox, DC, ox - dx1, oy - dy1, ox + dx2, oy + dy2, width, gcolor );
ox + dx1, oy + dy1, break;
width, gcolor);
GRCSegm(&panel->m_ClipBox, DC, ox - dx2, oy - dy2, case SKETCH:
ox + dx2, oy + dy2, GRCSegm( &panel->m_ClipBox, DC, ox - dx1, oy - dy1,
width, gcolor); ox + dx1, oy + dy1,
break; width, gcolor );
} GRCSegm( &panel->m_ClipBox, DC, ox - dx2, oy - dy2,
ox + dx2, oy + dy2,
width, gcolor );
break;
}
}
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param refPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool MIREPCB::HitTest( const wxPoint& refPos )
{
int dX = refPos.x - m_Pos.x;
int dY = refPos.y - m_Pos.y;
int rayon = m_Size / 2;
return abs(dX)<=rayon && abs(dY)<=rayon;
} }
...@@ -7,31 +7,38 @@ ...@@ -7,31 +7,38 @@
#include "base_struct.h" #include "base_struct.h"
class MIREPCB: public EDA_BaseStruct class MIREPCB : public EDA_BaseStruct
{ {
public: public:
int m_Layer; // 0.. 32 ( NON bit a bit) int m_Layer; // 0.. 32 ( NON bit a bit)
int m_Width; int m_Width;
wxPoint m_Pos; wxPoint m_Pos;
int m_Shape; // bit 0 : 0 = forme +, 1 = forme X int m_Shape; // bit 0 : 0 = forme +, 1 = forme X
int m_Size; int m_Size;
public: public:
MIREPCB(EDA_BaseStruct * StructFather); MIREPCB( EDA_BaseStruct* StructFather );
~MIREPCB(void); ~MIREPCB( void );
bool WriteMirePcbDescr(FILE * File); bool WriteMirePcbDescr( FILE* File );
bool ReadMirePcbDescr(FILE * File, int * LineNum); bool ReadMirePcbDescr( FILE* File, int* LineNum );
/* supprime du chainage la structure Struct */ /* supprime du chainage la structure Struct */
void UnLink( void ); void UnLink( void );
void Copy(MIREPCB * source); void Copy( MIREPCB* source );
void Draw(WinEDA_DrawPanel * panel, wxDC * DC, const wxPoint & offset, int mode_color); void Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& offset, int mode_color );
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param refPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool HitTest( const wxPoint& refPos );
}; };
#endif // #define MIRE_H
#endif // #define MIRE_H
...@@ -144,7 +144,6 @@ public: ...@@ -144,7 +144,6 @@ public:
#if defined(DEBUG) #if defined(DEBUG)
/** /**
* Function GetClass * Function GetClass
* returns the class name. * returns the class name.
......
...@@ -12,551 +12,665 @@ ...@@ -12,551 +12,665 @@
#include "cvpcb.h" #include "cvpcb.h"
#endif #endif
#include "trigo.h"
/**************************************/ /**************************************/
/* Classes pour Pistes, Vias et Zones */ /* Classes pour Pistes, Vias et Zones */
/**************************************/ /**************************************/
/* Constructeur des classes type pistes, vias et zones */ /* Constructeur des classes type pistes, vias et zones */
TRACK::TRACK(EDA_BaseStruct * StructFather, DrawStructureType idtype): TRACK::TRACK( EDA_BaseStruct* StructFather, DrawStructureType idtype ) :
EDA_BaseLineStruct( StructFather, idtype) EDA_BaseLineStruct( StructFather, idtype )
{ {
m_Shape = S_SEGMENT; m_Shape = S_SEGMENT;
start = end = NULL; start = end = NULL;
m_NetCode = 0; m_NetCode = 0;
m_Sous_Netcode = 0; m_Sous_Netcode = 0;
m_Drill = -1; m_Drill = -1;
m_Param = 0; m_Param = 0;
} }
SEGZONE::SEGZONE(EDA_BaseStruct * StructFather):
TRACK( StructFather, TYPEZONE) SEGZONE::SEGZONE( EDA_BaseStruct* StructFather ) :
TRACK( StructFather, TYPEZONE )
{ {
} }
SEGVIA::SEGVIA(EDA_BaseStruct * StructFather):
TRACK( StructFather, TYPEVIA) SEGVIA::SEGVIA( EDA_BaseStruct* StructFather ) :
TRACK( StructFather, TYPEVIA )
{ {
} }
/* Copy constructor */ /* Copy constructor */
TRACK::TRACK(const TRACK & Source): TRACK::TRACK( const TRACK& Source ) :
EDA_BaseLineStruct( Source.m_Parent, (DrawStructureType)Source.m_StructType) EDA_BaseLineStruct( Source.m_Parent, (DrawStructureType)Source.m_StructType )
{ {
m_StructType = Source.m_StructType; m_StructType = Source.m_StructType;
m_Shape = Source.m_Shape; m_Shape = Source.m_Shape;
m_NetCode = Source.m_NetCode; m_NetCode = Source.m_NetCode;
m_Flags = Source.m_Flags; m_Flags = Source.m_Flags;
m_TimeStamp = Source.m_TimeStamp; m_TimeStamp = Source.m_TimeStamp;
SetStatus(Source.ReturnStatus() ); SetStatus( Source.ReturnStatus() );
m_Layer = Source.m_Layer; m_Layer = Source.m_Layer;
m_Start = Source.m_Start; m_Start = Source.m_Start;
m_End = Source.m_End; m_End = Source.m_End;
m_Width = Source.m_Width; m_Width = Source.m_Width;
m_Drill = Source.m_Drill; m_Drill = Source.m_Drill;
m_Sous_Netcode = Source.m_Sous_Netcode; m_Sous_Netcode = Source.m_Sous_Netcode;
m_Param = Source.m_Param; m_Param = Source.m_Param;
} }
/***********************/ /***********************/
bool TRACK::IsNull(void) bool TRACK::IsNull( void )
/***********************/ /***********************/
// return TRUE if segment lenght = 0
// return TRUE if segment length = 0
{ {
if ( ( m_StructType != TYPEVIA ) && ( m_Start == m_End ) ) if( ( m_StructType != TYPEVIA ) && ( m_Start == m_End ) )
return TRUE; return TRUE;
else return FALSE; else
return FALSE;
} }
/*************************************************************/ /*************************************************************/
int TRACK::IsPointOnEnds(const wxPoint & point, int min_dist) int TRACK::IsPointOnEnds( const wxPoint& point, int min_dist )
/*************************************************************/ /*************************************************************/
/* Return: /* Return:
STARTPOINT if point if near (dist = min_dist) star point * STARTPOINT if point if near (dist = min_dist) star point
ENDPOINT if point if near (dist = min_dist) end point * ENDPOINT if point if near (dist = min_dist) end point
STARTPOINT|ENDPOINT if point if near (dist = min_dist) both ends * STARTPOINT|ENDPOINT if point if near (dist = min_dist) both ends
0 if no * 0 if no
if min_dist < 0: min_dist = track_width/2 * if min_dist < 0: min_dist = track_width/2
*/ */
{ {
int dx, dy; int dx, dy;
int result = 0; int result = 0;
if ( min_dist < 0 ) min_dist = m_Width / 2; if( min_dist < 0 )
min_dist = m_Width / 2;
dx = m_Start.x - point.x;
dy = m_Start.y - point.y; dx = m_Start.x - point.x;
if ( min_dist == 0 ) dy = m_Start.y - point.y;
{ if( min_dist == 0 )
if( (dx == 0) && (dy == 0 ) ) result |= STARTPOINT; {
} if( (dx == 0) && (dy == 0 ) )
else result |= STARTPOINT;
{ }
double dist = ((double)dx *dx) + ((double)dy*dy); else
dist = sqrt(dist); {
if ( min_dist >= (int) dist ) result |= STARTPOINT; double dist = ( (double) dx * dx ) + ( (double) dy * dy );
} dist = sqrt( dist );
if( min_dist >= (int) dist )
dx = m_End.x - point.x; result |= STARTPOINT;
dy = m_End.y - point.y; }
if ( min_dist == 0 )
{ dx = m_End.x - point.x;
if( (dx == 0) && (dy == 0 ) ) result |= ENDPOINT; dy = m_End.y - point.y;
} if( min_dist == 0 )
else {
{ if( (dx == 0) && (dy == 0 ) )
double dist = ((double)dx *dx) + ((double)dy*dy); result |= ENDPOINT;
dist = sqrt(dist); }
if ( min_dist >= (int) dist ) result |= ENDPOINT; else
} {
double dist = ( (double) dx * dx ) + ( (double) dy * dy );
return result; dist = sqrt( dist );
if( min_dist >= (int) dist )
result |= ENDPOINT;
}
return result;
} }
/******************************************/ /******************************************/
bool SEGVIA::IsViaOnLayer(int layer_number ) bool SEGVIA::IsViaOnLayer( int layer_number )
/******************************************/ /******************************************/
/* Retoune TRUE si Via sur layer layer_number /* Retoune TRUE si Via sur layer layer_number
*/ */
{ {
int via_type = Shape(); int via_type = Shape();
if( via_type == VIA_NORMALE ) if( via_type == VIA_NORMALE )
{ {
if ( layer_number <= LAYER_CMP_N ) return TRUE; if( layer_number <= LAYER_CMP_N )
else return FALSE; return TRUE;
} else
return FALSE;
// VIA_BORGNE ou VIA_ENTERREE: }
int bottom_layer, top_layer; // VIA_BORGNE ou VIA_ENTERREE:
ReturnLayerPair(& top_layer, & bottom_layer);
if ( (bottom_layer <= layer_number) && (top_layer >= layer_number) ) int bottom_layer, top_layer;
return TRUE; ReturnLayerPair( &top_layer, &bottom_layer );
else return FALSE; if( (bottom_layer <= layer_number) && (top_layer >= layer_number) )
return TRUE;
else
return FALSE;
} }
/***********************************/ /***********************************/
int TRACK::ReturnMaskLayer(void) int TRACK::ReturnMaskLayer( void )
/***********************************/ /***********************************/
/* Retourne le masque (liste bit a bit ) des couches occupees par le segment /* Retourne le masque (liste bit a bit ) des couches occupees par le segment
de piste pointe par PtSegm. * de piste pointe par PtSegm.
Si PtSegm pointe une via, il y a plusieurs couches occupees * Si PtSegm pointe une via, il y a plusieurs couches occupees
*/ */
{ {
if( m_StructType == TYPEVIA ) if( m_StructType == TYPEVIA )
{ {
int via_type = m_Shape & 15; int via_type = m_Shape & 15;
if( via_type == VIA_NORMALE ) return (ALL_CU_LAYERS); if( via_type == VIA_NORMALE )
// VIA_BORGNE ou VIA_ENTERREE: return ALL_CU_LAYERS;
int bottom_layer = (m_Layer >> 4) & 15;
int top_layer = m_Layer & 15; // VIA_BORGNE ou VIA_ENTERREE:
if ( bottom_layer > top_layer ) EXCHG (bottom_layer, top_layer); int bottom_layer = (m_Layer >> 4) & 15;
int layermask = 0; int top_layer = m_Layer & 15;
while ( bottom_layer <= top_layer ) if( bottom_layer > top_layer )
{ EXCHG( bottom_layer, top_layer );
layermask |= g_TabOneLayerMask[bottom_layer++]; int layermask = 0;
} while( bottom_layer <= top_layer )
return (layermask); {
} layermask |= g_TabOneLayerMask[bottom_layer++];
else return(g_TabOneLayerMask[m_Layer]); }
return layermask;
}
else
return g_TabOneLayerMask[m_Layer];
} }
/*********************************************************/ /*********************************************************/
void SEGVIA::SetLayerPair(int top_layer, int bottom_layer) void SEGVIA::SetLayerPair( int top_layer, int bottom_layer )
/*********************************************************/ /*********************************************************/
/* Met a jour .m_Layer pour une via: /* Met a jour .m_Layer pour une via:
m_Layer code les 2 couches limitant la via * m_Layer code les 2 couches limitant la via
*/ */
{ {
int via_type = m_Shape & 255; int via_type = m_Shape & 255;
if( via_type == VIA_NORMALE ) if( via_type == VIA_NORMALE )
{ {
top_layer = LAYER_CMP_N; bottom_layer = LAYER_CUIVRE_N; top_layer = LAYER_CMP_N; bottom_layer = LAYER_CUIVRE_N;
} }
if ( bottom_layer > top_layer ) EXCHG (bottom_layer, top_layer); if( bottom_layer > top_layer )
m_Layer = (top_layer & 15) + ( (bottom_layer & 15) << 4 ); EXCHG( bottom_layer, top_layer );
m_Layer = (top_layer & 15) + ( (bottom_layer & 15) << 4 );
} }
/***************************************************************/ /***************************************************************/
void SEGVIA::ReturnLayerPair(int * top_layer, int * bottom_layer) void SEGVIA::ReturnLayerPair( int* top_layer, int* bottom_layer )
/***************************************************************/ /***************************************************************/
/* Retourne les 2 couches limitant la via /* Retourne les 2 couches limitant la via
les pointeurs top_layer et bottom_layer peuvent etre NULLs * les pointeurs top_layer et bottom_layer peuvent etre NULLs
*/ */
{ {
int b_layer = (m_Layer >> 4) & 15; int b_layer = (m_Layer >> 4) & 15;
int t_layer = m_Layer & 15; int t_layer = m_Layer & 15;
if ( b_layer > t_layer ) EXCHG (b_layer, t_layer); if( b_layer > t_layer )
if ( top_layer ) * top_layer = t_layer; EXCHG( b_layer, t_layer );
if ( bottom_layer ) * bottom_layer = b_layer; if( top_layer )
*top_layer = t_layer;
if( bottom_layer )
*bottom_layer = b_layer;
} }
/************************/ /************************/
TRACK * TRACK::Next(void) TRACK* TRACK::Next( void )
/************************/ /************************/
{ {
return (TRACK *) Pnext; return (TRACK*) Pnext;
} }
/* supprime du chainage la structure Struct /* supprime du chainage la structure Struct
les structures arrieres et avant sont chainees directement * les structures arrieres et avant sont chainees directement
*/ */
void TRACK::UnLink( void ) void TRACK::UnLink( void )
{ {
/* Modification du chainage arriere */ /* Modification du chainage arriere */
if( Pback ) if( Pback )
{ {
if( Pback->m_StructType != TYPEPCB) if( Pback->m_StructType != TYPEPCB )
{ {
Pback->Pnext = Pnext; Pback->Pnext = Pnext;
} }
else /* Le chainage arriere pointe sur la structure "Pere" */
else /* Le chainage arriere pointe sur la structure "Pere" */ {
{ if( GetState( DELETED ) ) // A REVOIR car Pback = NULL si place en undelete
if ( GetState(DELETED) ) // A REVOIR car Pback = NULL si place en undelete {
{ if( g_UnDeleteStack )
if( g_UnDeleteStack ) g_UnDeleteStack[g_UnDeleteStackPtr-1] = Pnext; g_UnDeleteStack[g_UnDeleteStackPtr - 1] = Pnext;
} }
else else
{ {
if (m_StructType == TYPEZONE) if( m_StructType == TYPEZONE )
{ {
((BOARD*)Pback)->m_Zone = (TRACK*)Pnext; ( (BOARD*) Pback )->m_Zone = (TRACK*) Pnext;
} }
else else
{ {
((BOARD*)Pback)->m_Track = (TRACK*)Pnext; ( (BOARD*) Pback )->m_Track = (TRACK*) Pnext;
} }
} }
} }
} }
/* Modification du chainage avant */ /* Modification du chainage avant */
if( Pnext) Pnext->Pback = Pback; if( Pnext )
Pnext->Pback = Pback;
Pnext = Pback = NULL;
Pnext = Pback = NULL;
} }
/************************************************************/ /************************************************************/
void TRACK::Insert(BOARD * Pcb, EDA_BaseStruct * InsertPoint) void TRACK::Insert( BOARD* Pcb, EDA_BaseStruct* InsertPoint )
/************************************************************/ /************************************************************/
/* Ajoute un element ou une liste a une liste de base /* Ajoute un element ou une liste a une liste de base
Si Insertpoint == NULL: insertion en debut de * Si Insertpoint == NULL: insertion en debut de
liste Pcb->Track ou Pcb->Zone * liste Pcb->Track ou Pcb->Zone
Insertion a la suite de InsertPoint * Insertion a la suite de InsertPoint
Si InsertPoint == NULL, insertion en tete de liste * Si InsertPoint == NULL, insertion en tete de liste
*/ */
{ {
TRACK* track, *NextS; TRACK* track, * NextS;
/* Insertion du debut de la chaine a greffer */
if (InsertPoint == NULL) /* Insertion du debut de la chaine a greffer */
{ if( InsertPoint == NULL )
Pback = Pcb; {
if (m_StructType == TYPEZONE) Pback = Pcb;
{ if( m_StructType == TYPEZONE )
NextS = Pcb->m_Zone; Pcb->m_Zone = this; {
} NextS = Pcb->m_Zone; Pcb->m_Zone = this;
else }
{ else
NextS = Pcb->m_Track; Pcb->m_Track = this; {
} NextS = Pcb->m_Track; Pcb->m_Track = this;
} }
}
else else
{ {
NextS = (TRACK*)InsertPoint->Pnext; NextS = (TRACK*) InsertPoint->Pnext;
Pback = InsertPoint; Pback = InsertPoint;
InsertPoint->Pnext = this; InsertPoint->Pnext = this;
} }
/* Chainage de la fin de la liste a greffer */ /* Chainage de la fin de la liste a greffer */
track = this; track = this;
while ( track->Pnext ) track = (TRACK*) track->Pnext; while( track->Pnext )
/* Track pointe la fin de la chaine a greffer */ track = (TRACK*) track->Pnext;
track->Pnext = NextS;
if ( NextS ) NextS->Pback = track; /* Track pointe la fin de la chaine a greffer */
track->Pnext = NextS;
if( NextS )
NextS->Pback = track;
} }
/***********************************************/ /***********************************************/
TRACK * TRACK::GetBestInsertPoint( BOARD * Pcb ) TRACK* TRACK::GetBestInsertPoint( BOARD* Pcb )
/***********************************************/ /***********************************************/
/* Recherche du meilleur point d'insertion pour le nouveau segment de piste /* Recherche du meilleur point d'insertion pour le nouveau segment de piste
Retourne * Retourne
un pointeur sur le segment de piste APRES lequel l'insertion * un pointeur sur le segment de piste APRES lequel l'insertion
doit se faire ( dernier segment du net d'apartenance ) * doit se faire ( dernier segment du net d'apartenance )
NULL si pas de piste ( liste vide ); * NULL si pas de piste ( liste vide );
*/ */
{ {
TRACK * track, * NextTrack; TRACK* track, * NextTrack;
if( m_StructType == TYPEZONE ) track = Pcb->m_Zone; if( m_StructType == TYPEZONE )
else track = Pcb->m_Track; track = Pcb->m_Zone;
else
/* Traitement du debut de liste */ track = Pcb->m_Track;
if ( track == NULL ) return(NULL); /* pas de piste ! */
if ( m_NetCode < track->m_NetCode ) /* insertion en tete de liste */ /* Traitement du debut de liste */
return(NULL); if( track == NULL )
return NULL; /* pas de piste ! */
while( (NextTrack = (TRACK*)track->Pnext) != NULL ) if( m_NetCode < track->m_NetCode ) /* insertion en tete de liste */
{ return NULL;
if ( NextTrack->m_NetCode > this->m_NetCode ) break;
track = NextTrack; while( (NextTrack = (TRACK*) track->Pnext) != NULL )
} {
return ( track); if( NextTrack->m_NetCode > this->m_NetCode )
break;
track = NextTrack;
}
return track;
} }
/* Recherche du debut du net /* Recherche du debut du net
( les elements sont classes par net_code croissant ) * ( les elements sont classes par net_code croissant )
la recherche se fait a partir de this * la recherche se fait a partir de this
si net_code == -1 le netcode de this sera utilise * si net_code == -1 le netcode de this sera utilise
Retourne un pointeur sur le debut du net, ou NULL si net non trouve * Retourne un pointeur sur le debut du net, ou NULL si net non trouve
*/ */
TRACK * TRACK::GetStartNetCode(int NetCode ) TRACK* TRACK::GetStartNetCode( int NetCode )
{ {
TRACK * Track = this; TRACK* Track = this;
int ii = 0; int ii = 0;
if( NetCode == -1 ) NetCode = m_NetCode; if( NetCode == -1 )
NetCode = m_NetCode;
while( Track != NULL)
{ while( Track != NULL )
if ( Track->m_NetCode > NetCode ) break; {
if ( Track->m_NetCode == NetCode ) if( Track->m_NetCode > NetCode )
{ break;
ii++; break; if( Track->m_NetCode == NetCode )
} {
Track = (TRACK*) Track->Pnext; ii++; break;
} }
if ( ii ) return(Track); Track = (TRACK*) Track->Pnext;
else return (NULL); }
if( ii )
return Track;
else
return NULL;
} }
/* Recherche de la fin du net /* Recherche de la fin du net
Retourne un pointeur sur la fin du net, ou NULL si net non trouve * Retourne un pointeur sur la fin du net, ou NULL si net non trouve
*/ */
TRACK * TRACK::GetEndNetCode(int NetCode) TRACK* TRACK::GetEndNetCode( int NetCode )
{ {
TRACK * NextS, * Track = this; TRACK* NextS, * Track = this;
int ii = 0; int ii = 0;
if( Track == NULL ) return(NULL); if( Track == NULL )
return NULL;
if( NetCode == -1 ) NetCode = m_NetCode;
if( NetCode == -1 )
while( Track != NULL) NetCode = m_NetCode;
{
NextS = (TRACK*)Track->Pnext; while( Track != NULL )
if(Track->m_NetCode == NetCode) ii++; {
if ( NextS == NULL ) break; NextS = (TRACK*) Track->Pnext;
if ( NextS->m_NetCode > NetCode) break; if( Track->m_NetCode == NetCode )
Track = NextS; ii++;
} if( NextS == NULL )
if ( ii ) return(Track); break;
else return (NULL); if( NextS->m_NetCode > NetCode )
break;
Track = NextS;
}
if( ii )
return Track;
else
return NULL;
} }
/**********************************/ /**********************************/
TRACK * TRACK:: Copy( int NbSegm ) TRACK* TRACK:: Copy( int NbSegm )
/**********************************/ /**********************************/
/* Copie d'un Element ou d'une chaine de n elements /* Copie d'un Element ou d'une chaine de n elements
Retourne un pointeur sur le nouvel element ou le debut de la * Retourne un pointeur sur le nouvel element ou le debut de la
nouvelle chaine * nouvelle chaine
*/ */
{ {
TRACK * NewTrack, * FirstTrack, *OldTrack, * Source = this; TRACK* NewTrack, * FirstTrack, * OldTrack, * Source = this;
int ii; int ii;
FirstTrack = NewTrack = new TRACK(*Source); FirstTrack = NewTrack = new TRACK( *Source );
for( ii = 1; ii < NbSegm; ii++ ) for( ii = 1; ii < NbSegm; ii++ )
{ {
Source = Source->Next(); Source = Source->Next();
if( Source == NULL ) break; if( Source == NULL )
OldTrack = NewTrack; break;
NewTrack = new TRACK(*Source); OldTrack = NewTrack;
NewTrack->Insert(NULL, OldTrack); NewTrack = new TRACK( *Source );
} NewTrack->Insert( NULL, OldTrack );
}
return (FirstTrack);
return FirstTrack;
} }
/********************************************/ /********************************************/
bool TRACK::WriteTrackDescr(FILE * File) bool TRACK::WriteTrackDescr( FILE* File )
/********************************************/ /********************************************/
{ {
int type; int type;
type = 0; type = 0;
if( m_StructType == TYPEVIA ) type = 1; if( m_StructType == TYPEVIA )
type = 1;
if( GetState(DELETED) ) return FALSE; if( GetState( DELETED ) )
return FALSE;
fprintf( File,"Po %d %d %d %d %d %d %d\n",m_Shape, fprintf( File, "Po %d %d %d %d %d %d %d\n", m_Shape,
m_Start.x, m_Start.y, m_End.x, m_End.y, m_Width, m_Drill); m_Start.x, m_Start.y, m_End.x, m_End.y, m_Width, m_Drill );
fprintf( File,"De %d %d %d %lX %X\n", fprintf( File, "De %d %d %d %lX %X\n",
m_Layer, type ,m_NetCode, m_Layer, type, m_NetCode,
m_TimeStamp, ReturnStatus()); m_TimeStamp, ReturnStatus() );
return TRUE; return TRUE;
} }
/**********************************************************************/ /**********************************************************************/
void TRACK::Draw(WinEDA_DrawPanel * panel, wxDC * DC, int draw_mode) void TRACK::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode )
/*********************************************************************/ /*********************************************************************/
/* routine de trace de 1 segment de piste.
Parametres : /* routine de trace de 1 segment de piste.
draw_mode = mode ( GR_XOR, GR_OR..) * Parametres :
*/ * draw_mode = mode ( GR_XOR, GR_OR..)
*/
{ {
int l_piste; int l_piste;
int color; int color;
int zoom; int zoom;
int rayon; int rayon;
int curr_layer = ((PCB_SCREEN*)panel->GetScreen())->m_Active_Layer; int curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
if(m_StructType == TYPEZONE && (! DisplayOpt.DisplayZones) ) if( m_StructType == TYPEZONE && (!DisplayOpt.DisplayZones) )
return; return;
GRSetDrawMode(DC, draw_mode); GRSetDrawMode( DC, draw_mode );
if ( m_StructType == TYPEVIA ) /* VIA rencontree */ if( m_StructType == TYPEVIA ) /* VIA rencontree */
color = g_DesignSettings.m_ViaColor[m_Shape]; color = g_DesignSettings.m_ViaColor[m_Shape];
else color = g_DesignSettings.m_LayerColor[m_Layer]; else
color = g_DesignSettings.m_LayerColor[m_Layer];
if( (color & (ITEM_NOT_SHOW | HIGHT_LIGHT_FLAG)) == ITEM_NOT_SHOW) return ;
if( ( color & (ITEM_NOT_SHOW | HIGHT_LIGHT_FLAG) ) == ITEM_NOT_SHOW )
if ( DisplayOpt.ContrastModeDisplay ) return;
{
if ( m_StructType == TYPEVIA ) if( DisplayOpt.ContrastModeDisplay )
{ {
if ( ! ((SEGVIA*)this)->IsViaOnLayer(curr_layer) ) if( m_StructType == TYPEVIA )
{ {
color &= ~MASKCOLOR; if( !( (SEGVIA*) this )->IsViaOnLayer( curr_layer ) )
color |= DARKDARKGRAY; {
} color &= ~MASKCOLOR;
} color |= DARKDARKGRAY;
else if ( m_Layer != curr_layer) }
{ }
color &= ~MASKCOLOR; else if( m_Layer != curr_layer )
color |= DARKDARKGRAY; {
} color &= ~MASKCOLOR;
} color |= DARKDARKGRAY;
}
if( draw_mode & GR_SURBRILL) }
{
if( draw_mode & GR_AND) color &= ~HIGHT_LIGHT_FLAG; if( draw_mode & GR_SURBRILL )
else color |= HIGHT_LIGHT_FLAG; {
} if( draw_mode & GR_AND )
if ( color & HIGHT_LIGHT_FLAG) color &= ~HIGHT_LIGHT_FLAG;
color = ColorRefs[color & MASKCOLOR].m_LightColor; else
color |= HIGHT_LIGHT_FLAG;
zoom = panel->GetZoom(); }
if( color & HIGHT_LIGHT_FLAG )
l_piste = m_Width >> 1; color = ColorRefs[color & MASKCOLOR].m_LightColor;
if ( m_StructType == TYPEVIA ) /* VIA rencontree */ zoom = panel->GetZoom();
{
rayon = l_piste; if( rayon < zoom ) rayon = zoom; l_piste = m_Width >> 1;
GRCircle(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon, color) ;
if ( rayon > (4*zoom) ) if( m_StructType == TYPEVIA ) /* VIA rencontree */
{ {
int drill_rayon, inner_rayon = rayon-(2*zoom); rayon = l_piste; if( rayon < zoom )
GRCircle(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon = zoom;
inner_rayon, color); GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon, color );
// Draw the via hole if the display option request it if( rayon > (4 * zoom) )
if ( DisplayOpt.m_DisplayViaMode != VIA_HOLE_NOT_SHOW) {
{ int drill_rayon, inner_rayon = rayon - (2 * zoom);
if ( (DisplayOpt.m_DisplayViaMode == ALL_VIA_HOLE_SHOW) GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
|| ( m_Drill > 0 ) ) inner_rayon, color );
{
if ( m_Drill > 0 ) drill_rayon = m_Drill / 2; // Draw the via hole if the display option request it
else drill_rayon = g_DesignSettings.m_ViaDrill / 2; if( DisplayOpt.m_DisplayViaMode != VIA_HOLE_NOT_SHOW )
if( drill_rayon < inner_rayon ) // We can show the via hole {
{ if( (DisplayOpt.m_DisplayViaMode == ALL_VIA_HOLE_SHOW)
GRCircle(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, || ( m_Drill > 0 ) )
drill_rayon , color); {
} if( m_Drill > 0 )
} drill_rayon = m_Drill / 2;
} else
drill_rayon = g_DesignSettings.m_ViaDrill / 2;
if(DisplayOpt.DisplayTrackIsol) if( drill_rayon < inner_rayon ) // We can show the via hole
GRCircle(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, {
rayon + g_DesignSettings.m_TrackClearence, color); GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
} drill_rayon, color );
return; }
} }
}
if(m_Shape == S_CIRCLE)
{ if( DisplayOpt.DisplayTrackIsol )
rayon = (int)hypot((double)(m_End.x - m_Start.x), GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
(double)(m_End.y - m_Start.y) ); rayon + g_DesignSettings.m_TrackClearence, color );
if ( (l_piste/zoom) < L_MIN_DESSIN) }
{ return;
GRCircle(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon , color) ; }
}
if( m_Shape == S_CIRCLE )
else {
{ rayon = (int) hypot( (double) (m_End.x - m_Start.x),
if(l_piste <= zoom) /* trace simplifie si l_piste/zoom <= 1 */ (double) (m_End.y - m_Start.y) );
{ if( (l_piste / zoom) < L_MIN_DESSIN )
GRCircle(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon, color); {
} GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon, color );
else if( ( ! DisplayOpt.DisplayPcbTrackFill) || GetState(FORCE_SKETCH)) }
{ else
GRCircle(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon-l_piste, color); {
GRCircle(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon+l_piste, color); if( l_piste <= zoom ) /* trace simplifie si l_piste/zoom <= 1 */
} {
else GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon, color );
{ }
GRCircle(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon, else if( ( !DisplayOpt.DisplayPcbTrackFill) || GetState( FORCE_SKETCH ) )
m_Width, color); {
} GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon - l_piste, color );
} GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon + l_piste, color );
return; }
} else
{
if ( (l_piste/zoom) < L_MIN_DESSIN) GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon,
{ m_Width, color );
GRLine(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, }
m_End.x, m_End.y, 0, color); }
return; return;
} }
if( (! DisplayOpt.DisplayPcbTrackFill) || GetState(FORCE_SKETCH) ) if( (l_piste / zoom) < L_MIN_DESSIN )
{ {
GRCSegm(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, GRLine( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
m_End.x, m_End.y, m_Width, color) ; m_End.x, m_End.y, 0, color );
} return;
else }
{
GRFillCSegm(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, if( (!DisplayOpt.DisplayPcbTrackFill) || GetState( FORCE_SKETCH ) )
m_End.x, m_End.y, m_Width, color) ; {
} GRCSegm( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
m_End.x, m_End.y, m_Width, color );
/* Trace de l'isolation (pour segments type CUIVRE et TRACK uniquement */ }
if( (DisplayOpt.DisplayTrackIsol) && (m_Layer <= CMP_N ) else
&& ( m_StructType == TYPETRACK) ) {
{ GRFillCSegm( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
GRCSegm(&panel->m_ClipBox, DC, m_Start.x, m_Start.y, m_End.x, m_End.y, m_Width, color );
m_End.x, m_End.y, }
m_Width + (g_DesignSettings.m_TrackClearence*2), color) ;
} /* Trace de l'isolation (pour segments type CUIVRE et TRACK uniquement */
if( (DisplayOpt.DisplayTrackIsol) && (m_Layer <= CMP_N )
&& ( m_StructType == TYPETRACK) )
{
GRCSegm( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
m_End.x, m_End.y,
m_Width + (g_DesignSettings.m_TrackClearence * 2), color );
}
} }
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param ref_pos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool TRACK::HitTest( const wxPoint& ref_pos )
{
int l_piste; /* demi-largeur de la piste */
int dx, dy, spot_cX, spot_cY;
int ux0, uy0;
/* calcul des coordonnees du segment teste */
l_piste = m_Width >> 1; /* l_piste = demi largeur piste */
ux0 = m_Start.x;
uy0 = m_Start.y; /* coord de depart */
dx = m_End.x;
dy = m_End.y; /* coord d'arrivee */
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx -= ux0;
dy -= uy0;
spot_cX = ref_pos.x - ux0;
spot_cY = ref_pos.y - uy0;
if( m_StructType == TYPEVIA ) /* VIA rencontree */
{
if( (abs( spot_cX ) <= l_piste ) && (abs( spot_cY ) <=l_piste) )
return true;
else
return false;
}
else
{
if( DistanceTest( l_piste, dx, dy, spot_cX, spot_cY ) )
return true;
}
return false;
}
...@@ -10,84 +10,135 @@ ...@@ -10,84 +10,135 @@
/* Type des Vias (shape)*/ /* Type des Vias (shape)*/
/* Forme des Vias ( parametre .shape ) */ /* Forme des Vias ( parametre .shape ) */
#define VIA_NORMALE 3 /* type via : traversante (throught via) */ #define VIA_NORMALE 3 /* type via : traversante (throught via) */
#define VIA_ENTERREE 2 /* type via : enterree ou aveugle (blind via) */ #define VIA_ENTERREE 2 /* type via : enterree ou aveugle (blind via) */
#define VIA_BORGNE 1 /* type via : borgne ou demi-traversante (buried via) */ #define VIA_BORGNE 1 /* type via : borgne ou demi-traversante (buried via) */
#define VIA_NOT_DEFINED 0 /* reserved */ #define VIA_NOT_DEFINED 0 /* reserved */
#define SQUARE_VIA 0x80000000 /* Flag pour forme carree */ #define SQUARE_VIA 0x80000000 /* Flag pour forme carree */
/***/ /***/
class TRACK: public EDA_BaseLineStruct class TRACK : public EDA_BaseLineStruct
{ {
public: public:
int m_Shape; // vias: shape and type, Track = shape.. int m_Shape; // vias: shape and type, Track = shape..
int m_Drill; // for vias: via drill (- 1 for default value) int m_Drill; // for vias: via drill (- 1 for default value)
EDA_BaseStruct * start,* end; // pointers on a connected item (pad or track) EDA_BaseStruct* start, * end; // pointers on a connected item (pad or track)
int m_NetCode; // Net number int m_NetCode; // Net number
int m_Sous_Netcode; /* In rastnest routines : for the current net, int m_Sous_Netcode; /* In rastnest routines : for the current net,
block number (number common to the current connected items found) */ * block number (number common to the current connected items found) */
// chain = 0 indique une connexion non encore traitee
int m_Param; // Auxiliary variable ( used in some computations )
public: // chain = 0 indique une connexion non encore traitee
TRACK(EDA_BaseStruct * StructFather, DrawStructureType idtype = TYPETRACK); int m_Param; // Auxiliary variable ( used in some computations )
TRACK(const TRACK & track);
TRACK * Next(void); // Retourne le chainage avant
TRACK * Back(void) // Retourne le chainage avant
{
return (TRACK*) Pback;
}
/* supprime du chainage la structure Struct */
void UnLink( void );
// Read/write data
bool WriteTrackDescr(FILE * File);
/* Ajoute un element a la liste */
void Insert(BOARD * Pcb, EDA_BaseStruct * InsertPoint);
/* Recherche du meilleur point d'insertion */
TRACK * GetBestInsertPoint( BOARD * Pcb);
/* Copie d'un Element d'une chaine de n elements */ public:
TRACK * Copy( int NbSegm = 1 ); TRACK( EDA_BaseStruct* StructFather, DrawStructureType idtype = TYPETRACK );
TRACK( const TRACK& track );
/* Recherche du debut du net
( les elements sont classes par net_code croissant ) */ TRACK* Next( void ); // Retourne le chainage avant
TRACK * GetStartNetCode(int NetCode );
/* Recherche de la fin du net */ TRACK* Back( void ) // Retourne le chainage avant
TRACK * GetEndNetCode(int NetCode); {
return (TRACK*) Pback;
/* Display on screen: */ }
void Draw(WinEDA_DrawPanel * panel, wxDC * DC, int draw_mode);
/* divers */ /* supprime du chainage la structure Struct */
int Shape(void) { return m_Shape & 0xFF; } void UnLink( void );
int ReturnMaskLayer(void); // Read/write data
int IsPointOnEnds(const wxPoint & point, int min_dist = 0); bool WriteTrackDescr( FILE* File );
bool IsNull(void); // return TRUE if segment lenght = 0
/* Ajoute un element a la liste */
void Insert( BOARD* Pcb, EDA_BaseStruct* InsertPoint );
/* Recherche du meilleur point d'insertion */
TRACK* GetBestInsertPoint( BOARD* Pcb );
/* Copie d'un Element d'une chaine de n elements */
TRACK* Copy( int NbSegm = 1 );
/* Recherche du debut du net
* ( les elements sont classes par net_code croissant ) */
TRACK* GetStartNetCode( int NetCode );
/* Recherche de la fin du net */
TRACK* GetEndNetCode( int NetCode );
/* Display on screen: */
void Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode );
/* divers */
int Shape( void ) { return m_Shape & 0xFF; }
int ReturnMaskLayer( void );
int IsPointOnEnds( const wxPoint& point, int min_dist = 0 );
bool IsNull( void ); // return TRUE if segment lenght = 0
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param refPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool HitTest( const wxPoint& refPos );
#if defined(DEBUG)
/**
* Function GetClass
* returns the class name.
* @return wxString
*/
wxString GetClass() const
{
return wxT("TRACK");
}
#endif
}; };
class SEGZONE: public TRACK class SEGZONE : public TRACK
{ {
public: public:
SEGZONE(EDA_BaseStruct * StructFather); SEGZONE( EDA_BaseStruct* StructFather );
#if defined(DEBUG)
/**
* Function GetClass
* returns the class name.
* @return wxString
*/
wxString GetClass() const
{
return wxT("ZONE");
}
#endif
}; };
class SEGVIA: public TRACK class SEGVIA : public TRACK
{ {
public: public:
SEGVIA(EDA_BaseStruct * StructFather); SEGVIA( EDA_BaseStruct* StructFather );
bool IsViaOnLayer(int layer); bool IsViaOnLayer( int layer );
void SetLayerPair(int top_layer, int bottom_layer); void SetLayerPair( int top_layer, int bottom_layer );
void ReturnLayerPair(int * top_layer, int * bottom_layer); void ReturnLayerPair( int* top_layer, int* bottom_layer );
#if defined(DEBUG)
/**
* Function GetClass
* returns the class name.
* @return wxString
*/
wxString GetClass() const
{
return wxT("VIA");
}
#endif
}; };
#endif /* CLASS_TRACK_H */ #endif /* CLASS_TRACK_H */
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#endif #endif
#include "protos.h" #include "protos.h"
#include "trigo.h"
/**************************************************************/ /**************************************************************/
...@@ -165,6 +166,61 @@ bool DRAWSEGMENT::ReadDrawSegmentDescr( FILE* File, int* LineNum ) ...@@ -165,6 +166,61 @@ bool DRAWSEGMENT::ReadDrawSegmentDescr( FILE* File, int* LineNum )
} }
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param ref_pos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool DRAWSEGMENT::HitTest( const wxPoint& ref_pos )
{
int ux0 = m_Start.x;
int uy0 = m_Start.y;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
int dx = m_End.x - ux0;
int dy = m_End.y - uy0;
int spot_cX = ref_pos.x - ux0;
int spot_cY = ref_pos.y - uy0;
if( m_Shape==S_CIRCLE || 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 ) <= (m_Width / 2) )
{
if( m_Shape == S_CIRCLE )
return true;
/* pour un arc, controle complementaire */
mouseAngle = (int) ArcTangente( spot_cY, spot_cX );
stAngle = (int) ArcTangente( dy, dx );
endAngle = stAngle + m_Angle;
if( endAngle > 3600 )
{
stAngle -= 3600;
endAngle -= 3600;
}
if( mouseAngle >= stAngle && mouseAngle <= endAngle )
return true;
}
}
else
{
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
return true;
}
return false;
}
/*******************/ /*******************/
/* Classe MARQUEUR */ /* Classe MARQUEUR */
/*******************/ /*******************/
......
/****************************/ /****************************/
/* DRC control */ /* DRC control */
/****************************/ /****************************/
#include "fctsys.h" #include "fctsys.h"
#include "gr_basic.h" #include "gr_basic.h"
...@@ -14,1345 +14,1542 @@ ...@@ -14,1345 +14,1542 @@
/* variables locales */ /* variables locales */
class WinEDA_DrcFrame; class WinEDA_DrcFrame;
WinEDA_DrcFrame * DrcFrame; WinEDA_DrcFrame* DrcFrame;
/* saving drc options */ /* saving drc options */
static bool s_Pad2PadTestOpt = true; static bool s_Pad2PadTestOpt = true;
static bool s_UnconnectedTestOpt = true; static bool s_UnconnectedTestOpt = true;
static bool s_ZonesTestOpt = false; static bool s_ZonesTestOpt = false;
static bool s_CreateRptFileOpt = false; static bool s_CreateRptFileOpt = false;
static FILE * s_RptFile = NULL; static FILE* s_RptFile = NULL;
static wxString s_RptFilename; static wxString s_RptFilename;
static int ErrorsDRC_Count; static int ErrorsDRC_Count;
static MARQUEUR * current_marqueur; /* Pour gestion des marqueurs sur pcb */ static MARQUEUR* current_marqueur; /* Pour gestion des marqueurs sur pcb */
static bool AbortDrc, DrcInProgress = FALSE; static bool AbortDrc, DrcInProgress = FALSE;
static int spot_cX, spot_cY; /* position d'elements a tester */ static int spot_cX, spot_cY; /* position d'elements a tester */
static int finx, finy; // coord relatives de l'extremite du segm de reference static int finx, finy; // coord relatives de l'extremite du segm de reference
static int segm_angle; // angle d'inclinaison du segment de reference en 0,1 degre static int segm_angle; // angle d'inclinaison du segment de reference en 0,1 degre
static int segm_long; // longueur du segment de reference static int segm_long; // longueur du segment de reference
static int xcliplo,ycliplo,xcliphi,ycliphi ; /* coord de la surface de securite du segment a comparer */ static int xcliplo, ycliplo, xcliphi, ycliphi; /* coord de la surface de securite du segment a comparer */
/* Routines Locales */ /* Routines Locales */
static int Pad_to_Pad_Isol(D_PAD * pad_ref, D_PAD * pad, const int dist_min); static int Pad_to_Pad_Isol( D_PAD* pad_ref, D_PAD* pad, const int dist_min );
static bool Test_Pad_to_Pads_Drc(WinEDA_BasePcbFrame *frame, wxDC * DC, D_PAD * pad_ref, static bool Test_Pad_to_Pads_Drc( WinEDA_BasePcbFrame* frame,
LISTE_PAD * start_buffer, LISTE_PAD * end_buffer, int max_size, bool show_err); wxDC* DC,
static int TestClearanceSegmToPad(const D_PAD* pad_to_test, int seg_width, int isol); D_PAD* pad_ref,
static int TestMarginToCircle(int cx, int cy, int rayon, int longueur); LISTE_PAD* start_buffer,
static int Tst_Ligne(int x1,int y1,int x2,int y2); LISTE_PAD* end_buffer,
static void Affiche_Erreur_DRC(WinEDA_DrawPanel * panel, wxDC * DC, BOARD * Pcb, int max_size,
TRACK * pt_ref, void * pt_item, int errnumber); bool show_err );
static void Affiche_Erreur_DRC(WinEDA_DrawPanel * panel, wxDC * DC, static int TestClearanceSegmToPad( const D_PAD* pad_to_test, int seg_width, int isol );
BOARD * Pcb, D_PAD * pad1, D_PAD * pad2); static int TestMarginToCircle( int cx, int cy, int rayon, int longueur );
static int Tst_Ligne( int x1, int y1, int x2, int y2 );
static void Affiche_Erreur_DRC( WinEDA_DrawPanel* panel, wxDC* DC, BOARD* Pcb,
TRACK* pt_ref, void* pt_item, int errnumber );
/*******************************************/ static void Affiche_Erreur_DRC( WinEDA_DrawPanel* panel, wxDC* DC,
/* Frame d'option et execution DRC general */ BOARD* Pcb, D_PAD* pad1, D_PAD* pad2 );
/*******************************************/
/*******************************************/
/* Frame d'option et execution DRC general */
/*******************************************/
#include "dialog_drc.cpp" #include "dialog_drc.cpp"
/***************************************************************/ /***************************************************************/
void WinEDA_DrcFrame::ListUnconnectedPads(wxCommandEvent & event) void WinEDA_DrcFrame::ListUnconnectedPads( wxCommandEvent& event )
/***************************************************************/ /***************************************************************/
{ {
if( (m_Parent->m_Pcb->m_Status_Pcb & LISTE_CHEVELU_OK) == 0 ) if( (m_Parent->m_Pcb->m_Status_Pcb & LISTE_CHEVELU_OK) == 0 )
{ {
m_Parent->Compile_Ratsnest( m_DC, TRUE); m_Parent->Compile_Ratsnest( m_DC, TRUE );
} }
if( m_Parent->m_Pcb->m_Ratsnest == NULL ) return; if( m_Parent->m_Pcb->m_Ratsnest == NULL )
return;
CHEVELU* Ratsnest = m_Parent->m_Pcb->m_Ratsnest;
int draw_mode = GR_SURBRILL | GR_OR; CHEVELU* Ratsnest = m_Parent->m_Pcb->m_Ratsnest;
WinEDA_DrawPanel * panel = m_Parent->DrawPanel; int draw_mode = GR_SURBRILL | GR_OR;
int ii; WinEDA_DrawPanel* panel = m_Parent->DrawPanel;
wxString msg; int ii;
float convert = 0.0001; wxString msg;
float convert = 0.0001;
msg = _("Look for active routes\n");
m_logWindow->AppendText(msg); msg = _( "Look for active routes\n" );
if ( s_RptFile ) fprintf(s_RptFile, "%s", CONV_TO_UTF8(msg) ); m_logWindow->AppendText( msg );
if( s_RptFile )
m_UnconnectedCount = 0; fprintf( s_RptFile, "%s", CONV_TO_UTF8( msg ) );
for( ii = m_Parent->m_Pcb->GetNumRatsnests() ;ii > 0; Ratsnest++, ii--)
{ m_UnconnectedCount = 0;
if( (Ratsnest->status & CH_ACTIF) == 0) continue; for( ii = m_Parent->m_Pcb->GetNumRatsnests(); ii > 0; Ratsnest++, ii-- )
m_UnconnectedCount++; {
if ( m_UnconnectedCount == 1 ) m_logWindow->AppendText(_("Unconnected found:\n") ); if( (Ratsnest->status & CH_ACTIF) == 0 )
D_PAD * pad = Ratsnest->pad_start; continue;
pad->Draw(panel, m_DC, wxPoint(0,0),draw_mode); m_UnconnectedCount++;
wxString pad_name = pad->ReturnStringPadName(); if( m_UnconnectedCount == 1 )
wxString module_name = ((MODULE*)(pad->m_Parent))->m_Reference->m_Text; m_logWindow->AppendText( _( "Unconnected found:\n" ) );
msg.Printf(_("%d > Pad %s (%s) @ %.4f,%.4f and "), m_UnconnectedCount, D_PAD* pad = Ratsnest->pad_start;
pad_name.GetData(), module_name.GetData(), pad->m_Pos.x * convert, pad->m_Pos.y * convert); pad->Draw( panel, m_DC, wxPoint( 0, 0 ), draw_mode );
m_logWindow->AppendText(msg); wxString pad_name = pad->ReturnStringPadName();
if ( s_RptFile ) fprintf(s_RptFile, "%s", CONV_TO_UTF8(msg) ); wxString module_name = ( (MODULE*) (pad->m_Parent) )->m_Reference->m_Text;
msg.Printf( _( "%d > Pad %s (%s) @ %.4f,%.4f and " ), m_UnconnectedCount,
pad = Ratsnest->pad_end; pad_name.GetData(), module_name.GetData(
pad->Draw(panel, m_DC, wxPoint(0,0),draw_mode); ), pad->m_Pos.x * convert, pad->m_Pos.y * convert );
pad_name = pad->ReturnStringPadName(); m_logWindow->AppendText( msg );
module_name = ((MODULE*)(pad->m_Parent))->m_Reference->m_Text; if( s_RptFile )
msg.Printf(_("Pad %s (%s) @ %.4f,%.4f\n"), fprintf( s_RptFile, "%s", CONV_TO_UTF8( msg ) );
pad_name.GetData(), module_name.GetData(), pad->m_Pos.x * convert, pad->m_Pos.y * convert);
m_logWindow->AppendText(msg); pad = Ratsnest->pad_end;
if ( s_RptFile ) fprintf(s_RptFile, "%s", CONV_TO_UTF8(msg) ); pad->Draw( panel, m_DC, wxPoint( 0, 0 ), draw_mode );
} pad_name = pad->ReturnStringPadName();
module_name = ( (MODULE*) (pad->m_Parent) )->m_Reference->m_Text;
if ( m_UnconnectedCount ) msg.Printf(_("Active routes: %d\n"), m_UnconnectedCount); msg.Printf( _( "Pad %s (%s) @ %.4f,%.4f\n" ),
else msg = _("OK! (No active routes)\n"); pad_name.GetData(), module_name.GetData(
m_logWindow->AppendText(msg); ), pad->m_Pos.x * convert, pad->m_Pos.y * convert );
if ( s_RptFile ) fprintf(s_RptFile, "%s", CONV_TO_UTF8(msg) ); m_logWindow->AppendText( msg );
if( s_RptFile )
fprintf( s_RptFile, "%s", CONV_TO_UTF8( msg ) );
}
if( m_UnconnectedCount )
msg.Printf( _( "Active routes: %d\n" ), m_UnconnectedCount );
else
msg = _( "OK! (No active routes)\n" );
m_logWindow->AppendText( msg );
if( s_RptFile )
fprintf( s_RptFile, "%s", CONV_TO_UTF8( msg ) );
} }
/****************************************************/ /****************************************************/
void WinEDA_DrcFrame::TestDrc(wxCommandEvent & event) void WinEDA_DrcFrame::TestDrc( wxCommandEvent& event )
/****************************************************/ /****************************************************/
{ {
int errors; int errors;
wxString msg; wxString msg;
if ( ! DrcInProgress ) if( !DrcInProgress )
{ {
if ( m_CreateRptCtrl->IsChecked() ) // Create a file rpt if( m_CreateRptCtrl->IsChecked() ) // Create a file rpt
{ {
s_RptFilename = m_RptFilenameCtrl->GetValue(); s_RptFilename = m_RptFilenameCtrl->GetValue();
if ( s_RptFilename.IsEmpty() ) OnButtonBrowseRptFileClick( event ); if( s_RptFilename.IsEmpty() )
if ( ! s_RptFilename.IsEmpty() ) s_RptFile = wxFopen(s_RptFilename, wxT("w")); OnButtonBrowseRptFileClick( event );
else s_RptFile = NULL; if( !s_RptFilename.IsEmpty() )
} s_RptFile = wxFopen( s_RptFilename, wxT( "w" ) );
else
if ( s_RptFile ) s_RptFile = NULL;
{ }
fprintf(s_RptFile, "Drc report for %s\n", CONV_TO_UTF8(m_Parent->m_CurrentScreen->m_FileName) );
char line[256]; if( s_RptFile )
fprintf(s_RptFile, "Created on %s\n", DateAndTime(line)); {
} fprintf( s_RptFile, "Drc report for %s\n",
CONV_TO_UTF8( m_Parent->m_CurrentScreen->m_FileName ) );
s_Pad2PadTestOpt = m_Pad2PadTestCtrl->IsChecked(); char line[256];
s_UnconnectedTestOpt = m_UnconnectedTestCtrl->IsChecked(); fprintf( s_RptFile, "Created on %s\n", DateAndTime( line ) );
s_ZonesTestOpt = m_ZonesTestCtrl->IsChecked(); }
AbortDrc = FALSE;
m_logWindow->Clear(); s_Pad2PadTestOpt = m_Pad2PadTestCtrl->IsChecked();
g_DesignSettings.m_TrackClearence = s_UnconnectedTestOpt = m_UnconnectedTestCtrl->IsChecked();
ReturnValueFromTextCtrl(*m_SetClearance, m_Parent->m_InternalUnits); s_ZonesTestOpt = m_ZonesTestCtrl->IsChecked();
/* Test DRC errors (clearance errors, bad connections .. */ AbortDrc = FALSE;
errors = m_Parent->Test_DRC(m_DC, m_Pad2PadTestCtrl->IsChecked(), m_ZonesTestCtrl->IsChecked()); m_logWindow->Clear();
/* Search for active routes (unconnected pads) */ g_DesignSettings.m_TrackClearence =
if ( m_UnconnectedTestCtrl->IsChecked() ) ListUnconnectedPads(event); ReturnValueFromTextCtrl( *m_SetClearance, m_Parent->m_InternalUnits );
else m_UnconnectedCount = 0; /* Test DRC errors (clearance errors, bad connections .. */
if ( errors ) errors = m_Parent->Test_DRC( m_DC, m_Pad2PadTestCtrl->IsChecked(
msg.Printf(_("** End Drc: %d errors **\n"),errors); ), m_ZonesTestCtrl->IsChecked() );
else if ( m_UnconnectedCount == 0 ) /* Search for active routes (unconnected pads) */
msg = _("** End Drc: No Error **\n"); if( m_UnconnectedTestCtrl->IsChecked() )
m_logWindow->AppendText(msg); ListUnconnectedPads( event );
else
if ( s_RptFile ) fprintf(s_RptFile, "%s", CONV_TO_UTF8(msg) ); m_UnconnectedCount = 0;
if( errors )
if ( s_RptFile ) msg.Printf( _( "** End Drc: %d errors **\n" ), errors );
{ else if( m_UnconnectedCount == 0 )
msg.Printf( _("Report file <%s> created\n"), s_RptFilename.GetData()); msg = _( "** End Drc: No Error **\n" );
m_logWindow->AppendText(msg); m_logWindow->AppendText( msg );
fclose(s_RptFile);
s_RptFile = NULL; if( s_RptFile )
} fprintf( s_RptFile, "%s", CONV_TO_UTF8( msg ) );
} if( s_RptFile )
else wxBell(); {
msg.Printf( _( "Report file <%s> created\n" ), s_RptFilename.GetData() );
m_logWindow->AppendText( msg );
fclose( s_RptFile );
s_RptFile = NULL;
}
}
else
wxBell();
} }
/*********************************************************/ /*********************************************************/
void WinEDA_DrcFrame::DelDRCMarkers(wxCommandEvent & event) void WinEDA_DrcFrame::DelDRCMarkers( wxCommandEvent& event )
/*********************************************************/ /*********************************************************/
{ {
if ( ! DrcInProgress ) if( !DrcInProgress )
{ {
m_Parent->Erase_Marqueurs(); m_Parent->Erase_Marqueurs();
m_Parent->DrawPanel->ReDraw(m_DC,TRUE); m_Parent->DrawPanel->ReDraw( m_DC, TRUE );
} }
else wxBell(); else
wxBell();
} }
/******************************************************/ /******************************************************/
void WinEDA_PcbFrame::Install_Test_DRC_Frame(wxDC * DC) void WinEDA_PcbFrame::Install_Test_DRC_Frame( wxDC* DC )
/******************************************************/ /******************************************************/
/* Test des isolements : teste les isolements des pistes et place un /* Test des isolements : teste les isolements des pistes et place un
marqueur sur les divers segments en defaut * marqueur sur les divers segments en defaut
Principe: * Principe:
Appelle la routine drc() pour chaque segment de piste existant * Appelle la routine drc() pour chaque segment de piste existant
*/ */
{ {
AbortDrc = FALSE; AbortDrc = FALSE;
DrcFrame = new WinEDA_DrcFrame(this, DC); DrcFrame = new WinEDA_DrcFrame( this, DC );
DrcFrame->ShowModal(); DrcFrame->Destroy(); DrcFrame->ShowModal(); DrcFrame->Destroy();
DrcFrame = NULL; DrcFrame = NULL;
} }
/************************************************************************/ /************************************************************************/
int WinEDA_PcbFrame::Test_DRC(wxDC * DC, bool TestPad2Pad, bool TestZone) int WinEDA_PcbFrame::Test_DRC( wxDC* DC, bool TestPad2Pad, bool TestZone )
/************************************************************************/ /************************************************************************/
/* Test des isolements : teste les isolements des pistes et place un /* Test des isolements : teste les isolements des pistes et place un
marqueur sur les divers segments en defaut * marqueur sur les divers segments en defaut
Principe: * Principe:
Appelle la routine drc() pour chaque segment de piste existant * Appelle la routine drc() pour chaque segment de piste existant
*/ */
{ {
int ii, jj, old_net; int ii, jj, old_net;
int flag_err_Drc; int flag_err_Drc;
TRACK * pt_segm; TRACK* pt_segm;
D_PAD * pad; D_PAD* pad;
MARQUEUR * Marqueur; MARQUEUR* Marqueur;
EDA_BaseStruct * PtStruct; EDA_BaseStruct* PtStruct;
wxString Line; wxString Line;
#define PRINT_NB_PAD_POS 42
#define PRINT_PAD_ERR_POS 48 #define PRINT_NB_PAD_POS 42
#define PRINT_TST_POS 20 #define PRINT_PAD_ERR_POS 48
#define PRINT_NB_SEGM_POS 26 #define PRINT_TST_POS 20
#define PRINT_TRACK_ERR_POS 32 #define PRINT_NB_SEGM_POS 26
#define PRINT_TRACK_ERR_POS 32
#define PRINT_NB_ZONESEGM_POS 60 #define PRINT_NB_ZONESEGM_POS 60
#define PRINT_ZONE_ERR_POS 70 #define PRINT_ZONE_ERR_POS 70
DrcInProgress = TRUE; DrcInProgress = TRUE;
ErrorsDRC_Count = 0; ErrorsDRC_Count = 0;
Compile_Ratsnest(DC, TRUE); Compile_Ratsnest( DC, TRUE );
MsgPanel->EraseMsgBox(); MsgPanel->EraseMsgBox();
m_CurrentScreen->SetRefreshReq(); m_CurrentScreen->SetRefreshReq();
/* Effacement des anciens marqueurs */ /* Effacement des anciens marqueurs */
Erase_Marqueurs(); Erase_Marqueurs();
if ( TestPad2Pad ) /* Test DRC des pads entre eux */ if( TestPad2Pad ) /* Test DRC des pads entre eux */
{ {
Line.Printf( wxT("%d"),m_Pcb->m_NbPads) ; Line.Printf( wxT( "%d" ), m_Pcb->m_NbPads );
Affiche_1_Parametre(this, PRINT_NB_PAD_POS, wxT("NbPad"),Line,RED) ; Affiche_1_Parametre( this, PRINT_NB_PAD_POS, wxT( "NbPad" ), Line, RED );
Affiche_1_Parametre(this, PRINT_PAD_ERR_POS, wxT("Pad Err"), wxT("0"), LIGHTRED); Affiche_1_Parametre( this, PRINT_PAD_ERR_POS, wxT( "Pad Err" ), wxT( "0" ), LIGHTRED );
if ( DrcFrame ) DrcFrame->m_logWindow->AppendText(_("Tst Pad to Pad\n"));
LISTE_PAD * pad_list_start = CreateSortedPadListByXCoord(m_Pcb); if( DrcFrame )
LISTE_PAD * pad_list_limit = &pad_list_start[m_Pcb->m_NbPads]; DrcFrame->m_logWindow->AppendText( _( "Tst Pad to Pad\n" ) );
int max_size = 0;
LISTE_PAD * pad_list; LISTE_PAD* pad_list_start = CreateSortedPadListByXCoord( m_Pcb );
/* Compute the max size of the pads ( used to stop the test) */ LISTE_PAD* pad_list_limit = &pad_list_start[m_Pcb->m_NbPads];
for ( pad_list = pad_list_start; pad_list < pad_list_limit; pad_list++) int max_size = 0;
{ LISTE_PAD* pad_list;
pad = * pad_list; /* Compute the max size of the pads ( used to stop the test) */
if ( pad->m_Rayon > max_size ) max_size = pad->m_Rayon; for( pad_list = pad_list_start; pad_list < pad_list_limit; pad_list++ )
} {
/* Test the pads */ pad = *pad_list;
for ( pad_list = pad_list_start; pad_list < pad_list_limit; pad_list++) if( pad->m_Rayon > max_size )
{ max_size = pad->m_Rayon;
pad = * pad_list; }
if ( Test_Pad_to_Pads_Drc(this, DC, pad, pad_list, pad_list_limit, max_size, TRUE) == BAD_DRC )
{ /* Test the pads */
Marqueur = current_marqueur; for( pad_list = pad_list_start; pad_list < pad_list_limit; pad_list++ )
current_marqueur = NULL; {
if( Marqueur == NULL ) pad = *pad_list;
{ if( Test_Pad_to_Pads_Drc( this, DC, pad, pad_list, pad_list_limit, max_size,
DisplayError(this, wxT("Test_Drc(): internal err")); TRUE ) == BAD_DRC )
return ErrorsDRC_Count; {
} Marqueur = current_marqueur;
Line.Printf( wxT("%d"),ErrorsDRC_Count) ; current_marqueur = NULL;
Affiche_1_Parametre(this, PRINT_PAD_ERR_POS,wxEmptyString,Line, LIGHTRED); if( Marqueur == NULL )
Marqueur->Pnext = m_Pcb->m_Drawings; {
Marqueur->Pback = m_Pcb; DisplayError( this, wxT( "Test_Drc(): internal err" ) );
return ErrorsDRC_Count;
PtStruct = m_Pcb->m_Drawings; }
if(PtStruct) PtStruct->Pback = Marqueur; Line.Printf( wxT( "%d" ), ErrorsDRC_Count );
m_Pcb->m_Drawings = Marqueur; Affiche_1_Parametre( this, PRINT_PAD_ERR_POS, wxEmptyString, Line, LIGHTRED );
} Marqueur->Pnext = m_Pcb->m_Drawings;
} Marqueur->Pback = m_Pcb;
free(pad_list_start);
} PtStruct = m_Pcb->m_Drawings;
if( PtStruct )
/* Test track segments */ PtStruct->Pback = Marqueur;
Line.Printf( wxT("%d"),m_Pcb->m_NbSegmTrack) ; m_Pcb->m_Drawings = Marqueur;
Affiche_1_Parametre(this, PRINT_NB_SEGM_POS,_("SegmNb"),Line,RED) ; }
Affiche_1_Parametre(this, PRINT_TRACK_ERR_POS,_("Track Err"), wxT("0"), LIGHTRED); }
pt_segm = m_Pcb->m_Track;
free( pad_list_start );
if ( DrcFrame ) DrcFrame->m_logWindow->AppendText( _("Tst Tracks\n") ); }
for( ii = 0, old_net = -1, jj = 0; pt_segm != NULL; pt_segm = (TRACK*)pt_segm->Pnext, ii++, jj--)
{ /* Test track segments */
if( pt_segm->Pnext == NULL) break; Line.Printf( wxT( "%d" ), m_Pcb->m_NbSegmTrack );
if ( jj == 0 ) Affiche_1_Parametre( this, PRINT_NB_SEGM_POS, _( "SegmNb" ), Line, RED );
{ Affiche_1_Parametre( this, PRINT_TRACK_ERR_POS, _( "Track Err" ), wxT( "0" ), LIGHTRED );
jj = 10; pt_segm = m_Pcb->m_Track;
wxYield();
if(AbortDrc) if( DrcFrame )
{ DrcFrame->m_logWindow->AppendText( _( "Tst Tracks\n" ) );
AbortDrc = FALSE; break;
} for( ii = 0, old_net = -1, jj = 0;
/* Print stats */ pt_segm != NULL;
Line.Printf( wxT("%d"),ii); pt_segm = (TRACK*) pt_segm->Pnext, ii++, jj-- )
Affiche_1_Parametre(this, PRINT_TST_POS, wxT("Test"),Line,CYAN) ; {
} if( pt_segm->Pnext == NULL )
break;
if ( old_net != pt_segm->m_NetCode) if( jj == 0 )
{ {
wxString msg; jj = 10;
jj = 1; wxYield();
EQUIPOT * equipot = GetEquipot(m_Pcb, pt_segm->m_NetCode); if( AbortDrc )
if ( equipot ) msg = equipot->m_Netname + wxT(" "); {
else msg = wxT("<noname>"); AbortDrc = FALSE; break;
Affiche_1_Parametre(this, 0,_("Netname"),msg, YELLOW); }
old_net = pt_segm->m_NetCode; /* Print stats */
} Line.Printf( wxT( "%d" ), ii );
Affiche_1_Parametre( this, PRINT_TST_POS, wxT( "Test" ), Line, CYAN );
g_HightLigth_NetCode = pt_segm->m_NetCode; }
flag_err_Drc = Drc(this, DC, pt_segm,(TRACK*)pt_segm->Pnext, 1);
if(flag_err_Drc == BAD_DRC) if( old_net != pt_segm->m_NetCode )
{ {
Marqueur = current_marqueur; wxString msg;
current_marqueur = NULL; jj = 1;
if( Marqueur == NULL ) EQUIPOT* equipot = GetEquipot( m_Pcb, pt_segm->m_NetCode );
{ if( equipot )
DisplayError(this, wxT("Test_Drc(): internal err")); msg = equipot->m_Netname + wxT( " " );
return ErrorsDRC_Count; else
} msg = wxT( "<noname>" );
Marqueur->Pnext = m_Pcb->m_Drawings; Affiche_1_Parametre( this, 0, _( "Netname" ), msg, YELLOW );
Marqueur->Pback = m_Pcb; old_net = pt_segm->m_NetCode;
}
PtStruct = m_Pcb->m_Drawings;
if(PtStruct) PtStruct->Pback = Marqueur; g_HightLigth_NetCode = pt_segm->m_NetCode;
m_Pcb->m_Drawings = Marqueur; flag_err_Drc = Drc( this, DC, pt_segm, (TRACK*) pt_segm->Pnext, 1 );
if( flag_err_Drc == BAD_DRC )
GRSetDrawMode(DC, GR_OR); {
pt_segm->Draw(DrawPanel, DC, RED^LIGHTRED ); Marqueur = current_marqueur;
Line.Printf( wxT("%d"),ErrorsDRC_Count); current_marqueur = NULL;
Affiche_1_Parametre(this, PRINT_TRACK_ERR_POS,wxEmptyString,Line, LIGHTRED); if( Marqueur == NULL )
} {
} DisplayError( this, wxT( "Test_Drc(): internal err" ) );
return ErrorsDRC_Count;
/* Test zone segments segments */ }
if ( TestZone ) Marqueur->Pnext = m_Pcb->m_Drawings;
{ Marqueur->Pback = m_Pcb;
m_Pcb->m_NbSegmZone = 0;
for( pt_segm = (TRACK*)m_Pcb->m_Zone; pt_segm != NULL; pt_segm = (TRACK*)pt_segm->Pnext) PtStruct = m_Pcb->m_Drawings;
m_Pcb->m_NbSegmZone++; if( PtStruct )
Line.Printf( wxT("%d"),m_Pcb->m_NbSegmZone) ; PtStruct->Pback = Marqueur;
Affiche_1_Parametre(this, PRINT_NB_ZONESEGM_POS,_("SegmNb"),Line,RED) ; m_Pcb->m_Drawings = Marqueur;
Affiche_1_Parametre(this, PRINT_ZONE_ERR_POS,_("Zone Err"), wxT("0"), LIGHTRED);
GRSetDrawMode( DC, GR_OR );
if ( DrcFrame ) DrcFrame->m_logWindow->AppendText( _("Tst Zones\n") ); pt_segm->Draw( DrawPanel, DC, RED ^ LIGHTRED );
Line.Printf( wxT( "%d" ), ErrorsDRC_Count );
pt_segm = (TRACK*)m_Pcb->m_Zone; Affiche_1_Parametre( this, PRINT_TRACK_ERR_POS, wxEmptyString, Line, LIGHTRED );
for( ii = 0, old_net = -1, jj = 0; pt_segm != NULL; pt_segm = (TRACK*)pt_segm->Pnext, ii++, jj--) }
{ }
if( pt_segm->Pnext == NULL) break;
if ( jj == 0 ) /* Test zone segments segments */
{ if( TestZone )
jj = 100; {
wxYield(); m_Pcb->m_NbSegmZone = 0;
if(AbortDrc) for( pt_segm = (TRACK*) m_Pcb->m_Zone; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext )
{ m_Pcb->m_NbSegmZone++;
AbortDrc = FALSE; break;
} Line.Printf( wxT( "%d" ), m_Pcb->m_NbSegmZone );
/* Print stats */ Affiche_1_Parametre( this, PRINT_NB_ZONESEGM_POS, _( "SegmNb" ), Line, RED );
Line.Printf( wxT("%d"),ii); Affiche_1_Parametre( this, PRINT_ZONE_ERR_POS, _( "Zone Err" ), wxT( "0" ), LIGHTRED );
Affiche_1_Parametre(this, PRINT_TST_POS, wxT("Test"),Line,CYAN) ;
} if( DrcFrame )
DrcFrame->m_logWindow->AppendText( _( "Tst Zones\n" ) );
if ( old_net != pt_segm->m_NetCode)
{ pt_segm = (TRACK*) m_Pcb->m_Zone;
jj = 1; for( ii = 0, old_net = -1, jj = 0;
wxString msg; pt_segm != NULL;
EQUIPOT * equipot = GetEquipot(m_Pcb, pt_segm->m_NetCode); pt_segm = (TRACK*) pt_segm->Pnext, ii++, jj-- )
if ( equipot ) msg = equipot->m_Netname + wxT(" "); {
else msg = wxT("<noname>"); if( pt_segm->Pnext == NULL )
Affiche_1_Parametre(this, 0,_("Netname"),msg, YELLOW); break;
old_net = pt_segm->m_NetCode; if( jj == 0 )
} {
g_HightLigth_NetCode = pt_segm->m_NetCode; jj = 100;
/* Test drc with other zone segments, and pads */ wxYield();
flag_err_Drc = Drc(this, DC, pt_segm,(TRACK*)pt_segm->Pnext, 1); if( AbortDrc )
if(flag_err_Drc == BAD_DRC) {
{ AbortDrc = FALSE; break;
Marqueur = current_marqueur; }
current_marqueur = NULL; /* Print stats */
if( Marqueur == NULL ) Line.Printf( wxT( "%d" ), ii );
{ Affiche_1_Parametre( this, PRINT_TST_POS, wxT( "Test" ), Line, CYAN );
DisplayError(this, wxT("Test_Drc(): internal err")); }
return ErrorsDRC_Count;
} if( old_net != pt_segm->m_NetCode )
Marqueur->Pnext = m_Pcb->m_Drawings; {
Marqueur->Pback = m_Pcb; jj = 1;
wxString msg;
PtStruct = m_Pcb->m_Drawings; EQUIPOT* equipot = GetEquipot( m_Pcb, pt_segm->m_NetCode );
if(PtStruct) PtStruct->Pback = Marqueur; if( equipot )
m_Pcb->m_Drawings = Marqueur; msg = equipot->m_Netname + wxT( " " );
else
GRSetDrawMode(DC, GR_OR); msg = wxT( "<noname>" );
pt_segm->Draw(DrawPanel, DC, RED^LIGHTRED ); Affiche_1_Parametre( this, 0, _( "Netname" ), msg, YELLOW );
Line.Printf( wxT("%d"),ErrorsDRC_Count); old_net = pt_segm->m_NetCode;
Affiche_1_Parametre(this, PRINT_ZONE_ERR_POS, wxEmptyString, Line, LIGHTRED); }
} g_HightLigth_NetCode = pt_segm->m_NetCode;
/* Test drc with other zone segments, and pads */
/* Test drc with track segments */ flag_err_Drc = Drc( this, DC, pt_segm, (TRACK*) pt_segm->Pnext, 1 );
int tmp = m_Pcb->m_NbPads; m_Pcb->m_NbPads = 0; // Pads already tested: disable pad test if( flag_err_Drc == BAD_DRC )
flag_err_Drc = Drc(this, DC, pt_segm, m_Pcb->m_Track, 1); {
m_Pcb->m_NbPads = tmp; Marqueur = current_marqueur;
if(flag_err_Drc == BAD_DRC) current_marqueur = NULL;
{ if( Marqueur == NULL )
Marqueur = current_marqueur; {
current_marqueur = NULL; DisplayError( this, wxT( "Test_Drc(): internal err" ) );
if( Marqueur == NULL ) return ErrorsDRC_Count;
{ }
DisplayError(this, wxT("Test_Drc(): internal err")); Marqueur->Pnext = m_Pcb->m_Drawings;
return ErrorsDRC_Count; Marqueur->Pback = m_Pcb;
}
Marqueur->Pnext = m_Pcb->m_Drawings; PtStruct = m_Pcb->m_Drawings;
Marqueur->Pback = m_Pcb; if( PtStruct )
PtStruct->Pback = Marqueur;
PtStruct = m_Pcb->m_Drawings; m_Pcb->m_Drawings = Marqueur;
if(PtStruct) PtStruct->Pback = Marqueur;
m_Pcb->m_Drawings = Marqueur; GRSetDrawMode( DC, GR_OR );
pt_segm->Draw( DrawPanel, DC, RED ^ LIGHTRED );
GRSetDrawMode(DC, GR_OR); Line.Printf( wxT( "%d" ), ErrorsDRC_Count );
pt_segm->Draw(DrawPanel, DC, RED^LIGHTRED ); Affiche_1_Parametre( this, PRINT_ZONE_ERR_POS, wxEmptyString, Line, LIGHTRED );
Line.Printf( wxT("%d"),ErrorsDRC_Count); }
Affiche_1_Parametre(this, PRINT_ZONE_ERR_POS, wxEmptyString, Line, LIGHTRED);
} /* Test drc with track segments */
} int tmp = m_Pcb->m_NbPads; m_Pcb->m_NbPads = 0; // Pads already tested: disable pad test
} flag_err_Drc = Drc( this, DC, pt_segm, m_Pcb->m_Track, 1 );
m_Pcb->m_NbPads = tmp;
AbortDrc = FALSE;
DrcInProgress = FALSE; if( flag_err_Drc == BAD_DRC )
return ErrorsDRC_Count; {
Marqueur = current_marqueur;
current_marqueur = NULL;
if( Marqueur == NULL )
{
DisplayError( this, wxT( "Test_Drc(): internal err" ) );
return ErrorsDRC_Count;
}
Marqueur->Pnext = m_Pcb->m_Drawings;
Marqueur->Pback = m_Pcb;
PtStruct = m_Pcb->m_Drawings;
if( PtStruct )
PtStruct->Pback = Marqueur;
m_Pcb->m_Drawings = Marqueur;
GRSetDrawMode( DC, GR_OR );
pt_segm->Draw( DrawPanel, DC, RED ^ LIGHTRED );
Line.Printf( wxT( "%d" ), ErrorsDRC_Count );
Affiche_1_Parametre( this, PRINT_ZONE_ERR_POS, wxEmptyString, Line, LIGHTRED );
}
}
}
AbortDrc = FALSE;
DrcInProgress = FALSE;
return ErrorsDRC_Count;
} }
/***********************************************************************/ /***********************************************************************/
int Drc(WinEDA_BasePcbFrame *frame, wxDC * DC, int Drc( WinEDA_BasePcbFrame* frame, wxDC* DC,
TRACK * pt_segment, TRACK * StartBuffer, int show_err) TRACK* pt_segment, TRACK* StartBuffer, int show_err )
/***********************************************************************/ /***********************************************************************/
/* /*
Teste le segment en cours de trace: * Teste le segment en cours de trace:
pt_segment = pointeur sur segment a controler * pt_segment = pointeur sur segment a controler
StartBuffer = adresse de la zone des pistes a controler * StartBuffer = adresse de la zone des pistes a controler
(typiquement m_Pcb->m_Track) * (typiquement m_Pcb->m_Track)
show_err (flag) si 0 pas d'affichage d'erreur sur ecran * show_err (flag) si 0 pas d'affichage d'erreur sur ecran
retourne : * retourne :
BAD_DRC (1) si Violation DRC * BAD_DRC (1) si Violation DRC
OK_DRC (0) si OK * OK_DRC (0) si OK
*/ */
{ {
int ii ; int ii;
TRACK * pttrack; TRACK* pttrack;
int x0,y0,xf,yf ; // coord des extremites du segment teste dans le repere modifie int x0, y0, xf, yf; // coord des extremites du segment teste dans le repere modifie
int dx, dy; // utilise pour calcul des dim x et dim y des segments int dx, dy; // utilise pour calcul des dim x et dim y des segments
int w_dist; int w_dist;
int MaskLayer ; int MaskLayer;
int net_code_ref; int net_code_ref;
int org_X, org_Y; // Origine sur le PCB des axes du repere centre sur int org_X, org_Y; // Origine sur le PCB des axes du repere centre sur
// l'origine du segment de reference // l'origine du segment de reference
wxPoint shape_pos; wxPoint shape_pos;
org_X = pt_segment->m_Start.x; org_Y = pt_segment->m_Start.y ; org_X = pt_segment->m_Start.x; org_Y = pt_segment->m_Start.y;
finx = dx = pt_segment->m_End.x - org_X ; finx = dx = pt_segment->m_End.x - org_X;
finy = dy = pt_segment->m_End.y - org_Y ; finy = dy = pt_segment->m_End.y - org_Y;
MaskLayer = pt_segment->ReturnMaskLayer(); MaskLayer = pt_segment->ReturnMaskLayer();
net_code_ref = pt_segment->m_NetCode; net_code_ref = pt_segment->m_NetCode;
segm_angle = 0; segm_angle = 0;
if( dx || dy) if( dx || dy )
{ {
/* calcul de l'angle d'inclinaison en 0,1 degre */ /* calcul de l'angle d'inclinaison en 0,1 degre */
segm_angle = ArcTangente(dy,dx); segm_angle = ArcTangente( dy, dx );
/* Calcul de la longueur du segment en segm_long : dx = longueur */ /* Calcul de la longueur du segment en segm_long : dx = longueur */
RotatePoint(&dx, &dy, segm_angle); /* segm_long = longueur, yf = 0 */ RotatePoint( &dx, &dy, segm_angle ); /* segm_long = longueur, yf = 0 */
} }
/* Ici le segment a ete tourne de segm_angle, et est horizontal, dx > 0 */ /* Ici le segment a ete tourne de segm_angle, et est horizontal, dx > 0 */
segm_long = dx; segm_long = dx;
/******************************************/ /******************************************/
/* Phase 1 : test DRC track to pads :*/ /* Phase 1 : test DRC track to pads :*/
/******************************************/ /******************************************/
/* calcul de la distance min aux pads : */ /* calcul de la distance min aux pads : */
w_dist = (unsigned)(pt_segment->m_Width >> 1 ) ; w_dist = (unsigned) (pt_segment->m_Width >> 1 );
for ( ii = 0 ; ii < frame->m_Pcb->m_NbPads ; ii++) for( ii = 0; ii < frame->m_Pcb->m_NbPads; ii++ )
{ {
D_PAD * pt_pad = frame->m_Pcb->m_Pads[ii]; D_PAD* pt_pad = frame->m_Pcb->m_Pads[ii];
/* Pas de probleme si les pads sont en surface autre que la couche, /* Pas de probleme si les pads sont en surface autre que la couche,
sauf si le trou de percage gene (cas des pastilles perces simple * sauf si le trou de percage gene (cas des pastilles perc�s simple
face sur CI double face */ * face sur CI double face */
if( (pt_pad->m_Masque_Layer & MaskLayer ) == 0 ) if( (pt_pad->m_Masque_Layer & MaskLayer ) == 0 )
{ {
/* We must test the pad hole. In order to use the function "TestClearanceSegmToPad", /* We must test the pad hole. In order to use the function "TestClearanceSegmToPad",
a pseudo pad is used, with a shape and a size like the hole */ * a pseudo pad is used, with a shape and a size like the hole */
if ( pt_pad->m_Drill.x == 0 ) continue; if( pt_pad->m_Drill.x == 0 )
D_PAD pseudo_pad((MODULE*)NULL); continue;
pseudo_pad.m_Size = pt_pad->m_Drill; D_PAD pseudo_pad( (MODULE*) NULL );
pseudo_pad.m_Pos = pt_pad->m_Pos;
pseudo_pad.m_PadShape = pt_pad->m_DrillShape; pseudo_pad.m_Size = pt_pad->m_Drill;
pseudo_pad.m_Orient = pt_pad->m_Orient; pseudo_pad.m_Pos = pt_pad->m_Pos;
pseudo_pad.ComputeRayon(); pseudo_pad.m_PadShape = pt_pad->m_DrillShape;
spot_cX = pseudo_pad.m_Pos.x - org_X; pseudo_pad.m_Orient = pt_pad->m_Orient;
spot_cY = pseudo_pad.m_Pos.y - org_Y; pseudo_pad.ComputeRayon();
if( TestClearanceSegmToPad(&pseudo_pad, w_dist, g_DesignSettings.m_TrackClearence) != OK_DRC ) spot_cX = pseudo_pad.m_Pos.x - org_X;
{ spot_cY = pseudo_pad.m_Pos.y - org_Y;
ErrorsDRC_Count++; if( TestClearanceSegmToPad( &pseudo_pad, w_dist,
if( show_err ) g_DesignSettings.m_TrackClearence ) != OK_DRC )
Affiche_Erreur_DRC(frame->DrawPanel, DC, {
frame->m_Pcb, pt_segment,pt_pad,0); ErrorsDRC_Count++;
return(BAD_DRC); if( show_err )
} Affiche_Erreur_DRC( frame->DrawPanel, DC,
continue; frame->m_Pcb, pt_segment, pt_pad, 0 );
} return BAD_DRC;
}
/* Le pad doit faire partie d'un net mais pas de probleme continue;
si le pad est du meme net */ }
if( pt_pad->m_NetCode && (net_code_ref == pt_pad->m_NetCode) )
continue ; /* Le pad doit faire partie d'un net mais pas de probleme
* si le pad est du meme net */
/* Test DRC pour les pads */ if( pt_pad->m_NetCode && (net_code_ref == pt_pad->m_NetCode) )
continue;
/* Test DRC pour les pads */
shape_pos = pt_pad->ReturnShapePos(); shape_pos = pt_pad->ReturnShapePos();
spot_cX = shape_pos.x - org_X; spot_cX = shape_pos.x - org_X;
spot_cY = shape_pos.y - org_Y; spot_cY = shape_pos.y - org_Y;
if( TestClearanceSegmToPad(pt_pad, w_dist, g_DesignSettings.m_TrackClearence) == OK_DRC ) continue ; if( TestClearanceSegmToPad( pt_pad, w_dist, g_DesignSettings.m_TrackClearence ) == OK_DRC )
continue;
/* extremite sur pad ou defaut d'isolation trouve */
else /* extremite sur pad ou defaut d'isolation trouve */
{ else
ErrorsDRC_Count++; {
if( show_err ) ErrorsDRC_Count++;
Affiche_Erreur_DRC(frame->DrawPanel, DC, if( show_err )
frame->m_Pcb, pt_segment,pt_pad,1); Affiche_Erreur_DRC( frame->DrawPanel, DC,
return(BAD_DRC); frame->m_Pcb, pt_segment, pt_pad, 1 );
} return BAD_DRC;
} }
}
/**********************************************/
/* Phase 2 : test DRC avec les autres pistes :*/ /**********************************************/
/**********************************************/ /* Phase 2 : test DRC avec les autres pistes :*/
/**********************************************/
/* Ici le segment de reference est sur l'axe X */
/* Ici le segment de reference est sur l'axe X */
/* Comparaison du segment de reference aux autres segments de piste */
pttrack = StartBuffer ; /* Comparaison du segment de reference aux autres segments de piste */
for ( ;pttrack != NULL ; pttrack = (TRACK*) pttrack->Pnext ) pttrack = StartBuffer;
{ for( ; pttrack != NULL; pttrack = (TRACK*) pttrack->Pnext )
//pas de probleme si le segment a tester est du meme net: {
if( net_code_ref == pttrack->m_NetCode ) continue ; //pas de probleme si le segment a tester est du meme net:
//pas de probleme si le segment a tester est sur une autre couche : if( net_code_ref == pttrack->m_NetCode )
if( (MaskLayer & pttrack->ReturnMaskLayer() ) == 0 ) continue ; continue;
/* calcul de la Distance mini = Isol+ rayon ou demi largeur seg ref //pas de probleme si le segment a tester est sur une autre couche :
+ rayon ou demi largeur seg a comparer */ if( ( MaskLayer & pttrack->ReturnMaskLayer() ) == 0 )
w_dist = pt_segment->m_Width >> 1; continue;
w_dist += pttrack->m_Width >> 1;
w_dist += g_DesignSettings.m_TrackClearence; /* calcul de la Distance mini = Isol+ rayon ou demi largeur seg ref
+ rayon ou demi largeur seg a comparer */
/* si le segment de reference est une via, le traitement est ici */ w_dist = pt_segment->m_Width >> 1;
if ( pt_segment->m_StructType == TYPEVIA ) w_dist += pttrack->m_Width >> 1;
{ w_dist += g_DesignSettings.m_TrackClearence;
int orgx, orgy; // origine du repere d'axe X = segment a comparer
int angle = 0; // angle du segment a tester; /* si le segment de reference est une via, le traitement est ici */
orgx = pttrack->m_Start.x; orgy = pttrack->m_Start.y; if( pt_segment->m_StructType == TYPEVIA )
dx = pttrack->m_End.x - orgx ; dy = pttrack->m_End.y - orgy; {
x0 = pt_segment->m_Start.x - orgx ; y0 = pt_segment->m_Start.y - orgy ; int orgx, orgy; // origine du repere d'axe X = segment a comparer
int angle = 0; // angle du segment a tester;
if( pttrack->m_StructType == TYPEVIA) /* Tst distance entre 2 vias */ orgx = pttrack->m_Start.x; orgy = pttrack->m_Start.y;
{ dx = pttrack->m_End.x - orgx; dy = pttrack->m_End.y - orgy;
if( (int)hypot((float)x0,(float)y0) < w_dist ) x0 = pt_segment->m_Start.x - orgx; y0 = pt_segment->m_Start.y - orgy;
{
ErrorsDRC_Count++; if( pttrack->m_StructType == TYPEVIA ) /* Tst distance entre 2 vias */
if( show_err) {
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,21); if( (int) hypot( (float) x0, (float) y0 ) < w_dist )
return(BAD_DRC) ; {
} ErrorsDRC_Count++;
} if( show_err )
else /* Tst distance de via a segment */ Affiche_Erreur_DRC( frame->DrawPanel,
{ DC,
/* calcul de l'angle */ frame->m_Pcb,
angle = ArcTangente(dy,dx); pt_segment,
pttrack,
/* Calcul des coord dans le nouveau repere */ 21 );
RotatePoint(&dx, &dy, angle); return BAD_DRC;
RotatePoint(&x0, &y0, angle); }
}
if( TestMarginToCircle(x0, y0, w_dist, dx) == BAD_DRC ) else /* Tst distance de via a segment */
{ {
ErrorsDRC_Count++; /* calcul de l'angle */
if(show_err) angle = ArcTangente( dy, dx );
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,20);
return(BAD_DRC) ; /* Calcul des coord dans le nouveau repere */
} RotatePoint( &dx, &dy, angle );
} RotatePoint( &x0, &y0, angle );
continue;
} if( TestMarginToCircle( x0, y0, w_dist, dx ) == BAD_DRC )
{
/* calcule x0,y0, xf,yf = coord de debut et fin du segment de piste ErrorsDRC_Count++;
a tester, dans le repere axe X = segment de reference */ if( show_err )
x0 = pttrack->m_Start.x - org_X ; y0 = pttrack->m_Start.y - org_Y ; Affiche_Erreur_DRC( frame->DrawPanel,
xf = pttrack->m_End.x - org_X ; yf = pttrack->m_End.y - org_Y ; DC,
frame->m_Pcb,
RotatePoint(&x0, &y0, segm_angle); RotatePoint(&xf, &yf, segm_angle); pt_segment,
pttrack,
if ( pttrack->m_StructType == TYPEVIA ) 20 );
{ return BAD_DRC;
if( TestMarginToCircle(x0, y0,w_dist,segm_long) == OK_DRC) continue; }
ErrorsDRC_Count++; }
if(show_err) continue;
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,21); }
return(BAD_DRC) ;
} /* calcule x0,y0, xf,yf = coord de debut et fin du segment de piste
* a tester, dans le repere axe X = segment de reference */
x0 = pttrack->m_Start.x - org_X; y0 = pttrack->m_Start.y - org_Y;
/* xf = pttrack->m_End.x - org_X; yf = pttrack->m_End.y - org_Y;
le segment de reference est Horizontal, par suite des modifs d'axe.
3 cas : segment a comparer parallele, perp ou incline RotatePoint( &x0, &y0, segm_angle ); RotatePoint( &xf, &yf, segm_angle );
*/
if ( y0 == yf ) // segments paralleles if( pttrack->m_StructType == TYPEVIA )
{ {
if ( abs(y0) >= w_dist ) continue ; if( TestMarginToCircle( x0, y0, w_dist, segm_long ) == OK_DRC )
if ( x0 > xf) EXCHG (x0,xf) ; /* pour que x0 <= xf */ continue;
ErrorsDRC_Count++;
if ( x0 > (-w_dist) && x0 < (segm_long + w_dist)) /* Risque de defaut */ if( show_err )
{ Affiche_Erreur_DRC( frame->DrawPanel, DC, frame->m_Pcb, pt_segment, pttrack, 21 );
/* test fin tenant compte des formes arrondies des extremites */ return BAD_DRC;
if ( x0 >= 0 && x0 <= segm_long ) }
{
ErrorsDRC_Count++;
if ( show_err ) /*
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,2); * le segment de reference est Horizontal, par suite des modifs d'axe.
return(BAD_DRC) ; * 3 cas : segment a comparer parallele, perp ou incline
} */
if( TestMarginToCircle(x0, y0, w_dist,segm_long) == BAD_DRC) if( y0 == yf ) // segments paralleles
{ {
ErrorsDRC_Count++; if( abs( y0 ) >= w_dist )
if(show_err) continue;
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,2); if( x0 > xf )
return(BAD_DRC) ; EXCHG( x0, xf ); /* pour que x0 <= xf */
}
} if( x0 > (-w_dist) && x0 < (segm_long + w_dist) ) /* Risque de defaut */
if ( xf > (-w_dist) && xf < (segm_long + w_dist)) {
{ /* test fin tenant compte des formes arrondies des extremites */
/* test fin tenant compte des formes arrondies des extremites */ if( x0 >= 0 && x0 <= segm_long )
if ( xf >= 0 && xf <= segm_long ) {
{ ErrorsDRC_Count++;
ErrorsDRC_Count++; if( show_err )
if(show_err) Affiche_Erreur_DRC( frame->DrawPanel,
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,3); DC,
return(BAD_DRC) ; frame->m_Pcb,
} pt_segment,
if( TestMarginToCircle(xf, yf, w_dist,segm_long) == BAD_DRC) pttrack,
{ 2 );
ErrorsDRC_Count++; return BAD_DRC;
if(show_err) }
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,3); if( TestMarginToCircle( x0, y0, w_dist, segm_long ) == BAD_DRC )
return(BAD_DRC) ; {
} ErrorsDRC_Count++;
} if( show_err )
Affiche_Erreur_DRC( frame->DrawPanel,
if ( x0 <=0 && xf >= 0 ) DC,
{ frame->m_Pcb,
ErrorsDRC_Count++; pt_segment,
if(show_err) pttrack,
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,4); 2 );
return(BAD_DRC) ; return BAD_DRC;
} }
} }
if( xf > (-w_dist) && xf < (segm_long + w_dist) )
else if ( x0 == xf ) // segments perpendiculaires {
{ /* test fin tenant compte des formes arrondies des extremites */
if ( (x0 <= (-w_dist)) || (x0 >= (segm_long + w_dist))) continue ; if( xf >= 0 && xf <= segm_long )
{
/* test si les segments se croisent */ ErrorsDRC_Count++;
if( y0 > yf ) EXCHG(y0, yf); if( show_err )
if( (y0 < 0) && (yf > 0) ) Affiche_Erreur_DRC( frame->DrawPanel,
{ DC,
ErrorsDRC_Count++; frame->m_Pcb,
if( show_err) pt_segment,
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,6); pttrack,
return(BAD_DRC); 3 );
} return BAD_DRC;
}
/* ici l'erreur est due a une extremite pres d'une extremite du segm if( TestMarginToCircle( xf, yf, w_dist, segm_long ) == BAD_DRC )
de reference */ {
if(TestMarginToCircle(x0,y0,w_dist,segm_long) == BAD_DRC) ErrorsDRC_Count++;
{ if( show_err )
ErrorsDRC_Count++; Affiche_Erreur_DRC( frame->DrawPanel,
if(show_err) DC,
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,7); frame->m_Pcb,
return(BAD_DRC) ; pt_segment,
} pttrack,
if(TestMarginToCircle(xf,yf,w_dist,segm_long) == BAD_DRC) 3 );
{ return BAD_DRC;
ErrorsDRC_Count++; }
if(show_err) }
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,8);
return(BAD_DRC) ; if( x0 <=0 && xf >= 0 )
} {
} ErrorsDRC_Count++;
else // segments quelconques entre eux */ if( show_err )
{ Affiche_Erreur_DRC( frame->DrawPanel, DC, frame->m_Pcb, pt_segment, pttrack, 4 );
int bflag = OK_DRC; return BAD_DRC;
/* calcul de la "surface de securite du segment de reference */ }
/* premiere passe : la piste est assimilee a un rectangle */ }
else if( x0 == xf ) // segments perpendiculaires
xcliplo = ycliplo = -w_dist; {
xcliphi = segm_long + w_dist; ycliphi = w_dist; if( ( x0 <= (-w_dist) ) || ( x0 >= (segm_long + w_dist) ) )
continue;
bflag = Tst_Ligne(x0,y0,xf,yf);
if (bflag == BAD_DRC) /* test si les segments se croisent */
{ if( y0 > yf )
/* 2eme passe : la piste a des extremites arrondies. EXCHG( y0, yf );
Si le defaut de drc est du a une extremite : le calcul if( (y0 < 0) && (yf > 0) )
est affine pour tenir compte de cet arrondi */ {
ErrorsDRC_Count++;
xcliplo = 0 ; xcliphi = segm_long ; if( show_err )
bflag = Tst_Ligne(x0,y0,xf,yf) ; Affiche_Erreur_DRC( frame->DrawPanel, DC, frame->m_Pcb, pt_segment, pttrack, 6 );
return BAD_DRC;
if(bflag == BAD_DRC) }
{
ErrorsDRC_Count++; /* ici l'erreur est due a une extremite pres d'une extremite du segm
if(show_err) * de reference */
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,9); if( TestMarginToCircle( x0, y0, w_dist, segm_long ) == BAD_DRC )
return(BAD_DRC) ; {
} ErrorsDRC_Count++;
if( show_err )
else // L'erreur est due a une extremite du segment de reference: Affiche_Erreur_DRC( frame->DrawPanel, DC, frame->m_Pcb, pt_segment, pttrack, 7 );
{ // il faut tester les extremites de ce segment return BAD_DRC;
int angle, rx0,ry0,rxf,ryf; }
x0 = pttrack->m_Start.x; y0 = pttrack->m_Start.y; if( TestMarginToCircle( xf, yf, w_dist, segm_long ) == BAD_DRC )
xf = pttrack->m_End.x; yf = pttrack->m_End.y; {
dx = xf - x0; dy = yf - y0; ErrorsDRC_Count++;
/* calcul de l'angle d'inclinaison en 0,1 degre */ if( show_err )
angle = ArcTangente(dy,dx); Affiche_Erreur_DRC( frame->DrawPanel, DC, frame->m_Pcb, pt_segment, pttrack, 8 );
/* Calcul de la longueur du segment: dx = longueur */ return BAD_DRC;
RotatePoint(&dx, &dy, angle); }
}
/* calcul des coord du segment de reference ds le repere else // segments quelconques entre eux */
d'axe X = segment courant en tst */ {
rx0 = pt_segment->m_Start.x - x0; int bflag = OK_DRC;
ry0 = pt_segment->m_Start.y - y0; /* calcul de la "surface de securite du segment de reference */
rxf = pt_segment->m_End.x - x0; /* premiere passe : la piste est assimilee a un rectangle */
ryf = pt_segment->m_End.y - y0;
xcliplo = ycliplo = -w_dist;
RotatePoint(&rx0,&ry0, angle); xcliphi = segm_long + w_dist; ycliphi = w_dist;
RotatePoint(&rxf,&ryf, angle);
if(TestMarginToCircle(rx0,ry0,w_dist,dx) == BAD_DRC) bflag = Tst_Ligne( x0, y0, xf, yf );
{ if( bflag == BAD_DRC )
ErrorsDRC_Count++; {
if(show_err) /* 2eme passe : la piste a des extremites arrondies.
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,10); * Si le defaut de drc est du a une extremite : le calcul
return(BAD_DRC) ; * est affine pour tenir compte de cet arrondi */
}
if(TestMarginToCircle(rxf,ryf,w_dist,dx) == BAD_DRC) xcliplo = 0; xcliphi = segm_long;
{ bflag = Tst_Ligne( x0, y0, xf, yf );
ErrorsDRC_Count++;
if(show_err) if( bflag == BAD_DRC )
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pt_segment,pttrack,11); {
return(BAD_DRC) ; ErrorsDRC_Count++;
} if( show_err )
} Affiche_Erreur_DRC( frame->DrawPanel,
} DC,
} frame->m_Pcb,
} pt_segment,
return(OK_DRC) ; pttrack,
9 );
return BAD_DRC;
}
else // L'erreur est due a une extremite du segment de reference:
{
// il faut tester les extremites de ce segment
int angle, rx0, ry0, rxf, ryf;
x0 = pttrack->m_Start.x; y0 = pttrack->m_Start.y;
xf = pttrack->m_End.x; yf = pttrack->m_End.y;
dx = xf - x0; dy = yf - y0;
/* calcul de l'angle d'inclinaison en 0,1 degre */
angle = ArcTangente( dy, dx );
/* Calcul de la longueur du segment: dx = longueur */
RotatePoint( &dx, &dy, angle );
/* calcul des coord du segment de reference ds le repere
* d'axe X = segment courant en tst */
rx0 = pt_segment->m_Start.x - x0;
ry0 = pt_segment->m_Start.y - y0;
rxf = pt_segment->m_End.x - x0;
ryf = pt_segment->m_End.y - y0;
RotatePoint( &rx0, &ry0, angle );
RotatePoint( &rxf, &ryf, angle );
if( TestMarginToCircle( rx0, ry0, w_dist, dx ) == BAD_DRC )
{
ErrorsDRC_Count++;
if( show_err )
Affiche_Erreur_DRC( frame->DrawPanel,
DC,
frame->m_Pcb,
pt_segment,
pttrack,
10 );
return BAD_DRC;
}
if( TestMarginToCircle( rxf, ryf, w_dist, dx ) == BAD_DRC )
{
ErrorsDRC_Count++;
if( show_err )
Affiche_Erreur_DRC( frame->DrawPanel,
DC,
frame->m_Pcb,
pt_segment,
pttrack,
11 );
return BAD_DRC;
}
}
}
}
}
return OK_DRC;
} }
/*****************************************************************************/ /*****************************************************************************/
static bool Test_Pad_to_Pads_Drc(WinEDA_BasePcbFrame *frame, wxDC * DC, D_PAD * pad_ref, static bool Test_Pad_to_Pads_Drc( WinEDA_BasePcbFrame* frame,
LISTE_PAD * start_buffer, LISTE_PAD * end_buffer, int max_size, bool show_err) wxDC* DC,
D_PAD* pad_ref,
LISTE_PAD* start_buffer,
LISTE_PAD* end_buffer,
int max_size,
bool show_err )
/*****************************************************************************/ /*****************************************************************************/
/* Teste l'isolation de pad_ref avec les autres pads. /* Teste l'isolation de pad_ref avec les autres pads.
end_buffer = upper limit of the pad list. * end_buffer = upper limit of the pad list.
max_size = size of the biggest pad (used to stop the test when the X distance is > max_size) * max_size = size of the biggest pad (used to stop the test when the X distance is > max_size)
*/ */
{ {
int MaskLayer; int MaskLayer;
D_PAD * pad; D_PAD* pad;
LISTE_PAD * pad_list = start_buffer; LISTE_PAD* pad_list = start_buffer;
MaskLayer = pad_ref->m_Masque_Layer & ALL_CU_LAYERS; MaskLayer = pad_ref->m_Masque_Layer & ALL_CU_LAYERS;
int x_limite = max_size + g_DesignSettings.m_TrackClearence + int x_limite = max_size + g_DesignSettings.m_TrackClearence +
pad_ref->m_Rayon + pad_ref->m_Pos.x; pad_ref->m_Rayon + pad_ref->m_Pos.x;
for ( ; pad_list < end_buffer ; pad_list++) for( ; pad_list < end_buffer; pad_list++ )
{ {
pad = * pad_list; pad = *pad_list;
if ( pad == pad_ref ) continue; if( pad == pad_ref )
continue;
/* We can stop the test when pad->m_Pos.x > x_limite
because the list is sorted by X values */ /* We can stop the test when pad->m_Pos.x > x_limite
if ( pad->m_Pos.x > x_limite ) break; * because the list is sorted by X values */
if( pad->m_Pos.x > x_limite )
/* Pas de probleme si les pads ne sont pas sur les memes couches cuivre*/ break;
if( (pad->m_Masque_Layer & MaskLayer ) == 0 ) continue;
/* Pas de probleme si les pads ne sont pas sur les memes couches cuivre*/
/* Le pad doit faire partie d'un net, if( (pad->m_Masque_Layer & MaskLayer ) == 0 )
mais pas de probleme si les pads sont du meme net */ continue;
if( pad->m_NetCode && (pad_ref->m_NetCode == pad->m_NetCode) )
continue ; /* Le pad doit faire partie d'un net,
* mais pas de probleme si les pads sont du meme net */
/* pas de pb si les pads sont du meme module et if( pad->m_NetCode && (pad_ref->m_NetCode == pad->m_NetCode) )
de la meme reference ( pads multiples ) */ continue;
if ( (pad->m_Parent == pad_ref->m_Parent) && (pad->m_NumPadName == pad_ref->m_NumPadName) )
continue; /* pas de pb si les pads sont du meme module et
* de la meme reference ( pads multiples ) */
if( Pad_to_Pad_Isol(pad_ref, pad, g_DesignSettings.m_TrackClearence) == OK_DRC ) continue ; if( (pad->m_Parent == pad_ref->m_Parent) && (pad->m_NumPadName == pad_ref->m_NumPadName) )
else /* defaut d'isolation trouve */ continue;
{
ErrorsDRC_Count++; if( Pad_to_Pad_Isol( pad_ref, pad, g_DesignSettings.m_TrackClearence ) == OK_DRC )
if( show_err ) continue;
Affiche_Erreur_DRC(frame->DrawPanel, DC, frame->m_Pcb, pad_ref, pad); else /* defaut d'isolation trouve */
return(BAD_DRC); {
} ErrorsDRC_Count++;
} if( show_err )
return OK_DRC; Affiche_Erreur_DRC( frame->DrawPanel, DC, frame->m_Pcb, pad_ref, pad );
return BAD_DRC;
}
}
return OK_DRC;
} }
/**************************************************************************************/ /**************************************************************************************/
static int Pad_to_Pad_Isol(D_PAD * pad_ref, D_PAD * pad, const int dist_min) static int Pad_to_Pad_Isol( D_PAD* pad_ref, D_PAD* pad, const int dist_min )
/***************************************************************************************/ /***************************************************************************************/
/* Return OK_DRC si clearance between pad_ref and pad is >= dist_min /* Return OK_DRC si clearance between pad_ref and pad is >= dist_min
or BAD_DRC if not */ * or BAD_DRC if not */
{ {
wxPoint rel_pos; wxPoint rel_pos;
int dist, diag; int dist, diag;
wxPoint shape_pos; wxPoint shape_pos;
int pad_angle; int pad_angle;
rel_pos = pad->ReturnShapePos(); rel_pos = pad->ReturnShapePos();
shape_pos = pad_ref->ReturnShapePos(); shape_pos = pad_ref->ReturnShapePos();
// rel_pos is pad position relative to the pad_ref position
rel_pos.x -= shape_pos.x; // rel_pos is pad position relative to the pad_ref position
rel_pos.y -= shape_pos.y; rel_pos.x -= shape_pos.x;
dist = (int) hypot( (double) rel_pos.x, (double) rel_pos.y); rel_pos.y -= shape_pos.y;
dist = (int) hypot( (double) rel_pos.x, (double) rel_pos.y );
diag = OK_DRC;
diag = OK_DRC;
/* tst rapide: si les cercles exinscrits sont distants de dist_min au moins,
il n'y a pas de risque: */ /* tst rapide: si les cercles exinscrits sont distants de dist_min au moins,
if ( (dist - pad_ref->m_Rayon - pad->m_Rayon) >= dist_min ) * il n'y a pas de risque: */
return OK_DRC; if( (dist - pad_ref->m_Rayon - pad->m_Rayon) >= dist_min )
return OK_DRC;
/* Ici les pads sont proches et les cercles exinxcrits sont trop proches
Selon les formes relatives il peut y avoir ou non erreur */ /* Ici les pads sont proches et les cercles exinxcrits sont trop proches
* Selon les formes relatives il peut y avoir ou non erreur */
bool swap_pads = false;
if ( (pad_ref->m_PadShape != CIRCLE) && (pad->m_PadShape == CIRCLE) ) bool swap_pads = false;
swap_pads = true; if( (pad_ref->m_PadShape != CIRCLE) && (pad->m_PadShape == CIRCLE) )
else if ( (pad_ref->m_PadShape != OVALE) && (pad->m_PadShape == OVALE) ) swap_pads = true;
swap_pads = true; else if( (pad_ref->m_PadShape != OVALE) && (pad->m_PadShape == OVALE) )
swap_pads = true;
if ( swap_pads )
{ if( swap_pads )
EXCHG (pad_ref, pad); {
rel_pos.x = - rel_pos.x; EXCHG( pad_ref, pad );
rel_pos.y = - rel_pos.y; rel_pos.x = -rel_pos.x;
} rel_pos.y = -rel_pos.y;
}
switch (pad_ref->m_PadShape)
{ switch( pad_ref->m_PadShape )
case CIRCLE: // pad_ref is like a track segment with a null lenght {
segm_long = 0; case CIRCLE: // pad_ref is like a track segment with a null lenght
segm_angle = 0; segm_long = 0;
finx = finy = 0; segm_angle = 0;
spot_cX = rel_pos.x; finx = finy = 0;
spot_cY = rel_pos.y; spot_cX = rel_pos.x;
diag = TestClearanceSegmToPad(pad, pad_ref->m_Rayon, dist_min ); spot_cY = rel_pos.y;
break; diag = TestClearanceSegmToPad( pad, pad_ref->m_Rayon, dist_min );
break;
case RECT:
RotatePoint(&rel_pos.x, &rel_pos.y, pad_ref->m_Orient); case RECT:
pad_angle = pad_ref->m_Orient + pad->m_Orient; // pad_angle = pad orient relative to the pad_ref orient RotatePoint( &rel_pos.x, &rel_pos.y, pad_ref->m_Orient );
NORMALIZE_ANGLE_POS(pad_angle); pad_angle = pad_ref->m_Orient + pad->m_Orient; // pad_angle = pad orient relative to the pad_ref orient
if ( pad->m_PadShape == RECT ) NORMALIZE_ANGLE_POS( pad_angle );
{ if( pad->m_PadShape == RECT )
wxSize size = pad->m_Size; {
if ( (pad_angle == 0) || (pad_angle == 900) || (pad_angle == 1800) || (pad_angle == 2700)) wxSize size = pad->m_Size;
{ if( (pad_angle == 0) || (pad_angle == 900) || (pad_angle == 1800) ||
if ( (pad_angle == 900) || (pad_angle == 2700) ) (pad_angle == 2700) )
{ {
EXCHG(size.x, size.y ); if( (pad_angle == 900) || (pad_angle == 2700) )
} {
// Test DRC: EXCHG( size.x, size.y );
diag = BAD_DRC; }
rel_pos.x = ABS(rel_pos.x); rel_pos.y = ABS(rel_pos.y);
if ( (rel_pos.x - ((size.x + pad_ref->m_Size.x)/2) ) >= dist_min ) // Test DRC:
diag = OK_DRC; diag = BAD_DRC;
if ( (rel_pos.y - ((size.y + pad_ref->m_Size.y)/2) ) >= dist_min ) rel_pos.x = ABS( rel_pos.x ); rel_pos.y = ABS( rel_pos.y );
diag = OK_DRC; if( ( rel_pos.x - ( (size.x + pad_ref->m_Size.x) / 2 ) ) >= dist_min )
} diag = OK_DRC;
if( ( rel_pos.y - ( (size.y + pad_ref->m_Size.y) / 2 ) ) >= dist_min )
else // Any other orient diag = OK_DRC;
{ /* TODO : any orient ... */ }
} else // Any other orient
} {
break; /* TODO : any orient ... */
}
case OVALE: /* an oval pad is like a track segment */ }
{ break;
/* Create and test a track segment with same dimensions */
int segm_width; case OVALE: /* an oval pad is like a track segment */
segm_angle = pad_ref->m_Orient; // Segment orient. {
if ( pad_ref->m_Size.y < pad_ref->m_Size.x ) /* We suppose the pad is an horizontal oval */ /* Create and test a track segment with same dimensions */
{ int segm_width;
segm_width = pad_ref->m_Size.y; segm_angle = pad_ref->m_Orient; // Segment orient.
segm_long = pad_ref->m_Size.x - pad_ref->m_Size.y; if( pad_ref->m_Size.y < pad_ref->m_Size.x ) /* We suppose the pad is an horizontal oval */
} {
else // it was a vertical oval, change to a rotated horizontal one segm_width = pad_ref->m_Size.y;
{ segm_long = pad_ref->m_Size.x - pad_ref->m_Size.y;
segm_width = pad_ref->m_Size.x; }
segm_long = pad_ref->m_Size.y - pad_ref->m_Size.x; else // it was a vertical oval, change to a rotated horizontal one
segm_angle += 900; {
} segm_width = pad_ref->m_Size.x;
/* the start point must be 0,0 and currently rel_pos is relative the center of pad coordinate */ segm_long = pad_ref->m_Size.y - pad_ref->m_Size.x;
int sx = - segm_long /2, sy = 0; // Start point coordinate of the horizontal equivalent segment segm_angle += 900;
RotatePoint(&sx, &sy, segm_angle); // True start point coordinate of the equivalent segment }
spot_cX = rel_pos.x + sx; /* the start point must be 0,0 and currently rel_pos is relative the center of pad coordinate */
spot_cY = rel_pos.y + sy; // pad position / segment origin int sx = -segm_long / 2, sy = 0; // Start point coordinate of the horizontal equivalent segment
finx = - sx; RotatePoint( &sx, &sy, segm_angle ); // True start point coordinate of the equivalent segment
finy = - sy; // end of segment coordinate spot_cX = rel_pos.x + sx;
diag = TestClearanceSegmToPad(pad, segm_width/2, dist_min); spot_cY = rel_pos.y + sy; // pad position / segment origin
break; finx = -sx;
} finy = -sy; // end of segment coordinate
diag = TestClearanceSegmToPad( pad, segm_width / 2, dist_min );
default: break;
/* TODO...*/ }
break;
} default:
return diag; /* TODO...*/
break;
}
return diag;
} }
/***************************************************************************/ /***************************************************************************/
static int TestClearanceSegmToPad(const D_PAD* pad_to_test, int w_segm, int dist_min) static int TestClearanceSegmToPad( const D_PAD* pad_to_test, int w_segm, int dist_min )
/****************************************************************************/ /****************************************************************************/
/* /*
Routine adaptee de la "distance()" (LOCATE.CPP) * Routine adaptee de la "distance()" (LOCATE.CPP)
teste la distance du pad au segment de droite en cours * teste la distance du pad au segment de droite en cours
*
retourne: * retourne:
0 si distance >= dist_min * 0 si distance >= dist_min
1 si distance < dist_min * 1 si distance < dist_min
Parametres d'appel: * Parametres d'appel:
pad_to_test = pointeur sur le pad a tester * pad_to_test = pointeur sur le pad a tester
w_segm = demi largeur du segment a tester * w_segm = demi largeur du segment a tester
dist_min = marge a respecter * dist_min = marge a respecter
*
en variables globales * en variables globales
segm_long = longueur du segment en test * segm_long = longueur du segment en test
segm_angle = angle d'inclinaison du segment; * segm_angle = angle d'inclinaison du segment;
finx, finy = coord fin du segment / origine * finx, finy = coord fin du segment / origine
spot_cX, spot_cY = position du pad / origine du segment * spot_cX, spot_cY = position du pad / origine du segment
*/ */
{ {
int p_dimx, p_dimy ; /* demi - dimensions X et Y du pad a controler */ int p_dimx, p_dimy; /* demi - dimensions X et Y du pad a controler */
int bflag; int bflag;
int orient; int orient;
int x0, y0, xf, yf ; int x0, y0, xf, yf;
int seuil; int seuil;
int deltay; int deltay;
seuil = w_segm + dist_min; seuil = w_segm + dist_min;
p_dimx = pad_to_test->m_Size.x >> 1 ; p_dimx = pad_to_test->m_Size.x >> 1;
p_dimy = pad_to_test->m_Size.y >> 1 ; p_dimy = pad_to_test->m_Size.y >> 1;
if (pad_to_test->m_PadShape == CIRCLE ) if( pad_to_test->m_PadShape == CIRCLE )
{ {
/* calcul des coord centre du pad dans le repere axe X confondu /* calcul des coord centre du pad dans le repere axe X confondu
avec le segment en tst */ * avec le segment en tst */
RotatePoint(&spot_cX, &spot_cY, segm_angle); RotatePoint( &spot_cX, &spot_cY, segm_angle );
return (TestMarginToCircle(spot_cX, spot_cY, seuil+p_dimx, segm_long)); return TestMarginToCircle( spot_cX, spot_cY, seuil + p_dimx, segm_long );
} }
else else
{ {
/* calcul de la "surface de securite" du pad de reference */ /* calcul de la "surface de securite" du pad de reference */
xcliplo = spot_cX - seuil - p_dimx ; xcliplo = spot_cX - seuil - p_dimx;
ycliplo = spot_cY - seuil - p_dimy; ycliplo = spot_cY - seuil - p_dimy;
xcliphi = spot_cX + seuil + p_dimx; xcliphi = spot_cX + seuil + p_dimx;
ycliphi = spot_cY + seuil + p_dimy; ycliphi = spot_cY + seuil + p_dimy;
x0 = y0 = 0 ; xf = finx; yf = finy ;
orient = pad_to_test->m_Orient; x0 = y0 = 0;
RotatePoint(&x0,&y0,spot_cX, spot_cY, -orient);
RotatePoint(&xf,&yf,spot_cX, spot_cY, -orient); xf = finx;
yf = finy;
bflag = Tst_Ligne(x0,y0,xf,yf) ;
orient = pad_to_test->m_Orient;
if (bflag == OK_DRC) return (OK_DRC);
/* Erreur DRC : analyse fine de la forme de la pastille */ RotatePoint( &x0, &y0, spot_cX, spot_cY, -orient );
RotatePoint( &xf, &yf, spot_cX, spot_cY, -orient );
switch (pad_to_test->m_PadShape )
{ bflag = Tst_Ligne( x0, y0, xf, yf );
default: return(BAD_DRC);
if( bflag == OK_DRC )
case OVALE : return OK_DRC;
/* test de la pastille ovale ramenee au type ovale vertical */ /* Erreur DRC : analyse fine de la forme de la pastille */
if (p_dimx > p_dimy)
{ switch( pad_to_test->m_PadShape )
EXCHG(p_dimx,p_dimy); orient += 900; {
if(orient >= 3600) orient -=3600; default:
} return BAD_DRC;
deltay = p_dimy - p_dimx;
/* ici: p_dimx = rayon, case OVALE:
delta = dist centre cercles a centre pad */ /* test de la pastille ovale ramenee au type ovale vertical */
if( p_dimx > p_dimy )
/* Test du rectangle separant les 2 demi cercles */ {
xcliplo = spot_cX - seuil - p_dimx; EXCHG( p_dimx, p_dimy ); orient += 900;
ycliplo = spot_cY - w_segm - deltay; if( orient >= 3600 )
xcliphi = spot_cX + seuil + p_dimx; orient -= 3600;
ycliphi = spot_cY + w_segm + deltay; }
deltay = p_dimy - p_dimx;
bflag = Tst_Ligne(x0,y0,xf,yf);
if (bflag == BAD_DRC) return(BAD_DRC); /* ici: p_dimx = rayon,
* delta = dist centre cercles a centre pad */
/* test des 2 cercles */
x0 = spot_cX; /* x0,y0 = centre du cercle superieur du pad ovale */ /* Test du rectangle separant les 2 demi cercles */
y0 = spot_cY + deltay; xcliplo = spot_cX - seuil - p_dimx;
RotatePoint(&x0,&y0, spot_cX, spot_cY, orient); ycliplo = spot_cY - w_segm - deltay;
RotatePoint(&x0,&y0, segm_angle); xcliphi = spot_cX + seuil + p_dimx;
bflag = TestMarginToCircle(x0,y0,p_dimx + seuil, segm_long); ycliphi = spot_cY + w_segm + deltay;
if( bflag == BAD_DRC) return(BAD_DRC);
bflag = Tst_Ligne( x0, y0, xf, yf );
x0 = spot_cX; /* x0,y0 = centre du cercle inferieur du pad ovale */ if( bflag == BAD_DRC )
y0 = spot_cY - deltay; return BAD_DRC;
RotatePoint(&x0,&y0, spot_cX, spot_cY, orient);
RotatePoint(&x0,&y0, segm_angle); /* test des 2 cercles */
bflag = TestMarginToCircle(x0,y0,p_dimx + seuil, segm_long); x0 = spot_cX; /* x0,y0 = centre du cercle superieur du pad ovale */
if( bflag == BAD_DRC) return(BAD_DRC); y0 = spot_cY + deltay;
break; RotatePoint( &x0, &y0, spot_cX, spot_cY, orient );
RotatePoint( &x0, &y0, segm_angle );
case RECT: /* 2 rectangle + 4 1/4 cercles a tester */ bflag = TestMarginToCircle( x0, y0, p_dimx + seuil, segm_long );
/* Test du rectangle dimx + seuil, dimy */ if( bflag == BAD_DRC )
xcliplo = spot_cX - p_dimx - seuil; return BAD_DRC;
ycliplo = spot_cY - p_dimy;
xcliphi = spot_cX + p_dimx + seuil; x0 = spot_cX; /* x0,y0 = centre du cercle inferieur du pad ovale */
ycliphi = spot_cY + p_dimy; y0 = spot_cY - deltay;
RotatePoint( &x0, &y0, spot_cX, spot_cY, orient );
bflag = Tst_Ligne(x0,y0,xf,yf); RotatePoint( &x0, &y0, segm_angle );
if (bflag == BAD_DRC) bflag = TestMarginToCircle( x0, y0, p_dimx + seuil, segm_long );
{ if( bflag == BAD_DRC )
return(BAD_DRC); return BAD_DRC;
} break;
/* Test du rectangle dimx , dimy + seuil */ case RECT: /* 2 rectangle + 4 1/4 cercles a tester */
xcliplo = spot_cX - p_dimx; /* Test du rectangle dimx + seuil, dimy */
ycliplo = spot_cY - p_dimy - seuil; xcliplo = spot_cX - p_dimx - seuil;
xcliphi = spot_cX + p_dimx; ycliplo = spot_cY - p_dimy;
ycliphi = spot_cY + p_dimy + seuil; xcliphi = spot_cX + p_dimx + seuil;
ycliphi = spot_cY + p_dimy;
bflag = Tst_Ligne(x0,y0,xf,yf);
if (bflag == BAD_DRC) bflag = Tst_Ligne( x0, y0, xf, yf );
{ if( bflag == BAD_DRC )
return(BAD_DRC); {
} return BAD_DRC;
}
/* test des 4 cercles ( surface d'solation autour des sommets */
/* test du coin sup. gauche du pad */ /* Test du rectangle dimx , dimy + seuil */
x0 = spot_cX - p_dimx; xcliplo = spot_cX - p_dimx;
y0 = spot_cY - p_dimy; ycliplo = spot_cY - p_dimy - seuil;
RotatePoint(&x0,&y0, spot_cX, spot_cY, orient); xcliphi = spot_cX + p_dimx;
RotatePoint(&x0,&y0, segm_angle); ycliphi = spot_cY + p_dimy + seuil;
bflag = TestMarginToCircle(x0, y0, seuil, segm_long);
if( bflag == BAD_DRC) bflag = Tst_Ligne( x0, y0, xf, yf );
{ if( bflag == BAD_DRC )
return(BAD_DRC); {
} return BAD_DRC;
}
/* test du coin sup. droit du pad */
x0 = spot_cX + p_dimx; /* test des 4 cercles ( surface d'solation autour des sommets */
y0 = spot_cY - p_dimy; /* test du coin sup. gauche du pad */
RotatePoint(&x0,&y0, spot_cX, spot_cY, orient); x0 = spot_cX - p_dimx;
RotatePoint(&x0,&y0, segm_angle); y0 = spot_cY - p_dimy;
bflag = TestMarginToCircle(x0, y0, seuil, segm_long); RotatePoint( &x0, &y0, spot_cX, spot_cY, orient );
if( bflag == BAD_DRC) RotatePoint( &x0, &y0, segm_angle );
{ bflag = TestMarginToCircle( x0, y0, seuil, segm_long );
return(BAD_DRC); if( bflag == BAD_DRC )
} {
return BAD_DRC;
/* test du coin inf. gauche du pad */ }
x0 = spot_cX - p_dimx;
y0 = spot_cY + p_dimy; /* test du coin sup. droit du pad */
RotatePoint(&x0,&y0, spot_cX, spot_cY, orient); x0 = spot_cX + p_dimx;
RotatePoint(&x0,&y0, segm_angle); y0 = spot_cY - p_dimy;
bflag = TestMarginToCircle(x0, y0, seuil, segm_long); RotatePoint( &x0, &y0, spot_cX, spot_cY, orient );
if( bflag == BAD_DRC) RotatePoint( &x0, &y0, segm_angle );
{ bflag = TestMarginToCircle( x0, y0, seuil, segm_long );
return(BAD_DRC); if( bflag == BAD_DRC )
} {
return BAD_DRC;
/* test du coin inf. droit du pad */ }
x0 = spot_cX + p_dimx;
y0 = spot_cY + p_dimy; /* test du coin inf. gauche du pad */
RotatePoint(&x0,&y0, spot_cX, spot_cY, orient); x0 = spot_cX - p_dimx;
RotatePoint(&x0,&y0, segm_angle); y0 = spot_cY + p_dimy;
bflag = TestMarginToCircle(x0, y0, seuil, segm_long); RotatePoint( &x0, &y0, spot_cX, spot_cY, orient );
if( bflag == BAD_DRC) RotatePoint( &x0, &y0, segm_angle );
{ bflag = TestMarginToCircle( x0, y0, seuil, segm_long );
return(BAD_DRC); if( bflag == BAD_DRC )
} {
return BAD_DRC;
break; }
} /* test du coin inf. droit du pad */
} x0 = spot_cX + p_dimx;
return(OK_DRC) ; y0 = spot_cY + p_dimy;
RotatePoint( &x0, &y0, spot_cX, spot_cY, orient );
RotatePoint( &x0, &y0, segm_angle );
bflag = TestMarginToCircle( x0, y0, seuil, segm_long );
if( bflag == BAD_DRC )
{
return BAD_DRC;
}
break;
}
}
return OK_DRC;
} }
/*******************************************************************/ /*******************************************************************/
static int TestMarginToCircle(int cx, int cy, int rayon, int longueur ) static int TestMarginToCircle( int cx, int cy, int rayon, int longueur )
/*******************************************************************/ /*******************************************************************/
/* /*
Routine analogue a TestClearanceSegmToPad. * Routine analogue a TestClearanceSegmToPad.
Calcul de la distance d'un cercle (via ronde, extremite de piste) * Calcul de la distance d'un cercle (via ronde, extremite de piste)
au segment de droite en cours de controle (segment de reference dans * au segment de droite en cours de controle (segment de reference dans
son repere ) * son repere )
parametres: * parametres:
cx, cy: centre du cercle (surface ronde) a tester, dans le repere * cx, cy: centre du cercle (surface ronde) a tester, dans le repere
segment de reference * segment de reference
rayon = rayon du cercle * rayon = rayon du cercle
longueur = longueur du segment dans son repere (i.e. coord de fin) * longueur = longueur du segment dans son repere (i.e. coord de fin)
retourne: * retourne:
OK_DRC si distance >= rayon * OK_DRC si distance >= rayon
BAD_DRC si distance < rayon * BAD_DRC si distance < rayon
*/ */
{ {
if ( abs(cy) > rayon) return(OK_DRC); if( abs( cy ) > rayon )
return OK_DRC;
if ( (cx >= -rayon ) && (cx <= (longueur+rayon) ) )
{ if( (cx >= -rayon ) && ( cx <= (longueur + rayon) ) )
if( (cx >= 0) && (cx <= longueur) ) return(BAD_DRC) ; {
if( cx > longueur) cx -= longueur ; if( (cx >= 0) && (cx <= longueur) )
if( hypot((double)cx, (double)cy) < rayon ) return(BAD_DRC); return BAD_DRC;
} if( cx > longueur )
cx -= longueur;
return(OK_DRC) ; if( hypot( (double) cx, (double) cy ) < rayon )
return BAD_DRC;
}
return OK_DRC;
} }
/******************************************************************************/ /******************************************************************************/
static void Affiche_Erreur_DRC(WinEDA_DrawPanel * panel, wxDC * DC, BOARD * Pcb, static void Affiche_Erreur_DRC( WinEDA_DrawPanel* panel, wxDC* DC, BOARD* Pcb,
TRACK * pt_ref, void * pt_item, int errnumber) TRACK* pt_ref, void* pt_item, int errnumber )
/******************************************************************************/ /******************************************************************************/
/* affiche les erreurs de DRC : /* affiche les erreurs de DRC :
Message d'erreur * Message d'erreur
+ +
Marqueur * Marqueur
number = numero d'identification * number = numero d'identification
*/ */
{ {
wxPoint erc_pos; wxPoint erc_pos;
TRACK * pt_segm; TRACK* pt_segm;
wxString msg; wxString msg;
wxString tracktype, netname1, netname2; wxString tracktype, netname1, netname2;
EQUIPOT * equipot = GetEquipot(Pcb, pt_ref->m_NetCode); EQUIPOT* equipot = GetEquipot( Pcb, pt_ref->m_NetCode );
if ( equipot ) netname1 = equipot->m_Netname;
else netname1 = wxT("<noname>"); if( equipot )
netname2 = wxT("<noname>"); netname1 = equipot->m_Netname;
else
tracktype = wxT("Track"); netname1 = wxT( "<noname>" );
if ( pt_ref->m_StructType == TYPEVIA ) tracktype = wxT("Via"); netname2 = wxT( "<noname>" );
if ( pt_ref->m_StructType == TYPEZONE ) tracktype = wxT("Zone");
tracktype = wxT( "Track" );
if( pt_ref->m_StructType == TYPEVIA )
if( ((EDA_BaseStruct*)pt_item)->m_StructType == TYPEPAD ) tracktype = wxT( "Via" );
{ if( pt_ref->m_StructType == TYPEZONE )
D_PAD * pad = (D_PAD*) pt_item; tracktype = wxT( "Zone" );
equipot = GetEquipot(Pcb, pad->m_NetCode);
if ( equipot ) netname2 = equipot->m_Netname;
erc_pos = pad->m_Pos; if( ( (EDA_BaseStruct*) pt_item )->m_StructType == TYPEPAD )
wxString pad_name = pad->ReturnStringPadName(); {
wxString module_name = ((MODULE*)(pad->m_Parent))->m_Reference->m_Text; D_PAD* pad = (D_PAD*) pt_item;
msg.Printf(_("%d Drc Err %d %s (net %s)and PAD %s (%s) net %s @ %d,%d\n"), equipot = GetEquipot( Pcb, pad->m_NetCode );
ErrorsDRC_Count, errnumber, tracktype.GetData(), if( equipot )
netname1.GetData(), netname2 = equipot->m_Netname;
pad_name.GetData(), module_name.GetData(), erc_pos = pad->m_Pos;
netname2.GetData(), wxString pad_name = pad->ReturnStringPadName();
erc_pos.x, erc_pos.y); wxString module_name = ( (MODULE*) (pad->m_Parent) )->m_Reference->m_Text;
} msg.Printf( _( "%d Drc Err %d %s (net %s)and PAD %s (%s) net %s @ %d,%d\n" ),
else /* erreur sur segment de piste */ ErrorsDRC_Count, errnumber, tracktype.GetData(),
{ netname1.GetData(),
pt_segm = (TRACK *) pt_item; pad_name.GetData(), module_name.GetData(),
equipot = GetEquipot(Pcb, pt_segm->m_NetCode); netname2.GetData(),
if ( equipot ) netname2 = equipot->m_Netname; erc_pos.x, erc_pos.y );
erc_pos = pt_segm->m_Start; }
if(pt_segm->m_StructType == TYPEVIA) else /* erreur sur segment de piste */
{ {
msg.Printf(_("%d Err type %d: %s (net %s) and VIA (net %s) @ %d,%d\n"), pt_segm = (TRACK*) pt_item;
ErrorsDRC_Count, errnumber, tracktype.GetData(), equipot = GetEquipot( Pcb, pt_segm->m_NetCode );
netname1.GetData(), netname2.GetData(), if( equipot )
erc_pos.x,erc_pos.y); netname2 = equipot->m_Netname;
} erc_pos = pt_segm->m_Start;
else if( pt_segm->m_StructType == TYPEVIA )
{ {
wxPoint erc_pos_f = pt_segm->m_End; msg.Printf( _( "%d Err type %d: %s (net %s) and VIA (net %s) @ %d,%d\n" ),
if(hypot( (double)(erc_pos_f.x - pt_ref->m_End.x),(double)(erc_pos_f.y - pt_ref->m_End.y) ) ErrorsDRC_Count, errnumber, tracktype.GetData(),
< hypot( (double)(erc_pos.x - pt_ref->m_End.x),(double)(erc_pos.y - pt_ref->m_End.y) ) ) netname1.GetData(), netname2.GetData(),
{ erc_pos.x, erc_pos.y );
EXCHG(erc_pos_f.x, erc_pos.x); EXCHG(erc_pos_f.y, erc_pos.y); }
} else
msg.Printf(_("%d Err type %d: %s (net %s) and track (net %s) @ %d,%d\n"), {
ErrorsDRC_Count, errnumber, tracktype.GetData(), wxPoint erc_pos_f = pt_segm->m_End;
netname1.GetData(), netname2.GetData(), if( hypot( (double) (erc_pos_f.x - pt_ref->m_End.x),
erc_pos.x,erc_pos.y); (double) (erc_pos_f.y - pt_ref->m_End.y) )
} < hypot( (double) (erc_pos.x - pt_ref->m_End.x),
} (double) (erc_pos.y - pt_ref->m_End.y) ) )
{
if ( DrcFrame ) DrcFrame->m_logWindow->AppendText(msg); EXCHG( erc_pos_f.x, erc_pos.x ); EXCHG( erc_pos_f.y, erc_pos.y );
else panel->m_Parent->Affiche_Message(msg); }
if ( s_RptFile ) fprintf(s_RptFile, "%s", CONV_TO_UTF8(msg) ); msg.Printf( _( "%d Err type %d: %s (net %s) and track (net %s) @ %d,%d\n" ),
ErrorsDRC_Count, errnumber, tracktype.GetData(),
if(current_marqueur == NULL) current_marqueur = new MARQUEUR(Pcb); netname1.GetData(), netname2.GetData(),
current_marqueur->m_Pos = wxPoint(erc_pos.x, erc_pos.y); erc_pos.x, erc_pos.y );
current_marqueur->m_Color = WHITE; }
current_marqueur->m_Diag = msg; }
current_marqueur->Draw(panel, DC, GR_OR);
if( DrcFrame )
DrcFrame->m_logWindow->AppendText( msg );
else
panel->m_Parent->Affiche_Message( msg );
if( s_RptFile )
fprintf( s_RptFile, "%s", CONV_TO_UTF8( msg ) );
if( current_marqueur == NULL )
current_marqueur = new MARQUEUR( Pcb );
current_marqueur->m_Pos = wxPoint( erc_pos.x, erc_pos.y );
current_marqueur->m_Color = WHITE;
current_marqueur->m_Diag = msg;
current_marqueur->Draw( panel, DC, GR_OR );
} }
/******************************************************************************/ /******************************************************************************/
static void Affiche_Erreur_DRC(WinEDA_DrawPanel * panel, wxDC * DC, BOARD * Pcb, static void Affiche_Erreur_DRC( WinEDA_DrawPanel* panel, wxDC* DC, BOARD* Pcb,
D_PAD * pad1, D_PAD * pad2) D_PAD* pad1, D_PAD* pad2 )
/******************************************************************************/ /******************************************************************************/
/* affiche les erreurs de DRC : /* affiche les erreurs de DRC :
Message d'erreur * Message d'erreur
+ +
Marqueur * Marqueur
number = numero d'identification * number = numero d'identification
*/ */
{ {
wxString msg; wxString msg;
wxString pad_name1 = pad1->ReturnStringPadName(); wxString pad_name1 = pad1->ReturnStringPadName();
wxString module_name1 = ((MODULE*)(pad1->m_Parent))->m_Reference->m_Text; wxString module_name1 = ( (MODULE*) (pad1->m_Parent) )->m_Reference->m_Text;
wxString pad_name2 = pad2->ReturnStringPadName(); wxString pad_name2 = pad2->ReturnStringPadName();
wxString module_name2 = ((MODULE*)(pad2->m_Parent))->m_Reference->m_Text; wxString module_name2 = ( (MODULE*) (pad2->m_Parent) )->m_Reference->m_Text;
wxString netname1, netname2; wxString netname1, netname2;
EQUIPOT * equipot = GetEquipot(Pcb, pad1->m_NetCode); EQUIPOT* equipot = GetEquipot( Pcb, pad1->m_NetCode );
if ( equipot ) netname1 = equipot->m_Netname;
else netname1 = wxT("<noname>"); if( equipot )
equipot = GetEquipot(Pcb, pad2->m_NetCode); netname1 = equipot->m_Netname;
if ( equipot ) netname2 = equipot->m_Netname; else
else netname2 = wxT("<noname>"); netname1 = wxT( "<noname>" );
equipot = GetEquipot( Pcb, pad2->m_NetCode );
msg.Printf( _("%d Drc Err: PAD %s (%s) net %s @ %d,%d and PAD %s (%s) net %s @ %d,%d\n"), if( equipot )
ErrorsDRC_Count, pad_name1.GetData(), module_name1.GetData(), netname2 = equipot->m_Netname;
netname1.GetData(), pad1->m_Pos.x,pad1->m_Pos.y, else
pad_name2.GetData(), module_name2.GetData(), netname2 = wxT( "<noname>" );
netname2.GetData(), pad2->m_Pos.x, pad2->m_Pos.y);
if ( DrcFrame ) DrcFrame->m_logWindow->AppendText(msg); msg.Printf( _( "%d Drc Err: PAD %s (%s) net %s @ %d,%d and PAD %s (%s) net %s @ %d,%d\n" ),
else panel->m_Parent->Affiche_Message(msg); ErrorsDRC_Count, pad_name1.GetData(), module_name1.GetData(),
if ( s_RptFile ) fprintf(s_RptFile, "%s", CONV_TO_UTF8(msg) ); netname1.GetData(), pad1->m_Pos.x, pad1->m_Pos.y,
pad_name2.GetData(), module_name2.GetData(),
if(current_marqueur == NULL) current_marqueur = new MARQUEUR(Pcb); netname2.GetData(), pad2->m_Pos.x, pad2->m_Pos.y );
current_marqueur->m_Pos = pad1->m_Pos; if( DrcFrame )
current_marqueur->m_Color = WHITE; DrcFrame->m_logWindow->AppendText( msg );
current_marqueur->m_Diag = msg; else
current_marqueur->Draw(panel, DC, GR_OR); panel->m_Parent->Affiche_Message( msg );
if( s_RptFile )
fprintf( s_RptFile, "%s", CONV_TO_UTF8( msg ) );
if( current_marqueur == NULL )
current_marqueur = new MARQUEUR( Pcb );
current_marqueur->m_Pos = pad1->m_Pos;
current_marqueur->m_Color = WHITE;
current_marqueur->m_Diag = msg;
current_marqueur->Draw( panel, DC, GR_OR );
} }
/**********************************************/ /**********************************************/
/* int Tst_Ligne(int x1,int y1,int x2,int y2) */ /* int Tst_Ligne(int x1,int y1,int x2,int y2) */
/**********************************************/ /**********************************************/
/* Routine utilisee pour tester si une piste est en contact avec une autre piste. /* Routine utilisee pour tester si une piste est en contact avec une autre piste.
*
Cette routine controle si la ligne (x1,y1 x2,y2) a une partie s'inscrivant * Cette routine controle si la ligne (x1,y1 x2,y2) a une partie s'inscrivant
dans le cadre (xcliplo,ycliplo xcliphi,ycliphi) (variables globales, * dans le cadre (xcliplo,ycliplo xcliphi,ycliphi) (variables globales,
locales a ce fichier) * locales a ce fichier)
*
Retourne OK_DRC si aucune partie commune * Retourne OK_DRC si aucune partie commune
Retourne BAD_DRC si partie commune * Retourne BAD_DRC si partie commune
*/ */
#define us unsigned int #define us unsigned int
static inline int USCALE(us arg, us num, us den) static inline int USCALE( us arg, us num, us den )
{ {
int ii; int ii;
ii = (int) ( ( (float) arg * num ) / den );
return ii;
}
ii = (int)( ((float) arg * num) / den);
return( ii );
}
#define WHEN_OUTSIDE return(OK_DRC) #define WHEN_OUTSIDE return (OK_DRC)
#define WHEN_INSIDE #define WHEN_INSIDE
static int Tst_Ligne(int x1,int y1,int x2,int y2) static int Tst_Ligne( int x1, int y1, int x2, int y2 )
{ {
int temp; int temp;
do { do {
if(x1 > x2) { EXCHG(x1,x2); EXCHG(y1,y2); } if( x1 > x2 )
if((x2 < xcliplo) || (x1 > xcliphi)) { WHEN_OUTSIDE; } {
if(y1 < y2) EXCHG( x1, x2 ); EXCHG( y1, y2 );
{ }
if((y2 < ycliplo) || (y1 > ycliphi)) { WHEN_OUTSIDE;} if( (x2 < xcliplo) || (x1 > xcliphi) )
if(y1 < ycliplo) {
{ WHEN_OUTSIDE;
temp = USCALE((x2 - x1),(ycliplo - y1),(y2 - y1)); }
if((x1 += temp) > xcliphi) { WHEN_OUTSIDE; } if( y1 < y2 )
y1 = ycliplo; {
WHEN_INSIDE; if( (y2 < ycliplo) || (y1 > ycliphi) )
} {
if(y2 > ycliphi) WHEN_OUTSIDE;
{ }
temp = USCALE((x2 - x1),(y2 - ycliphi),(y2 - y1)); if( y1 < ycliplo )
if((x2 -= temp) < xcliplo) { WHEN_OUTSIDE; } {
y2 = ycliphi; temp = USCALE( (x2 - x1), (ycliplo - y1), (y2 - y1) );
WHEN_INSIDE; if( (x1 += temp) > xcliphi )
} {
if(x1 < xcliplo) WHEN_OUTSIDE;
{ }
temp = USCALE((y2 - y1),(xcliplo - x1),(x2 - x1)); y1 = ycliplo;
y1 += temp; x1 = xcliplo; WHEN_INSIDE;
WHEN_INSIDE; }
} if( y2 > ycliphi )
if(x2 > xcliphi) {
{ temp = USCALE( (x2 - x1), (y2 - ycliphi), (y2 - y1) );
temp = USCALE((y2 - y1),(x2 - xcliphi),(x2 - x1)); if( (x2 -= temp) < xcliplo )
y2 -= temp; x2 = xcliphi; {
WHEN_INSIDE; WHEN_OUTSIDE;
} }
} y2 = ycliphi;
else WHEN_INSIDE;
{ }
if((y1 < ycliplo) || (y2 > ycliphi)) { WHEN_OUTSIDE; } if( x1 < xcliplo )
if(y1 > ycliphi) {
{ temp = USCALE( (y2 - y1), (xcliplo - x1), (x2 - x1) );
temp = USCALE((x2 - x1),(y1 - ycliphi),(y1 - y2)); y1 += temp; x1 = xcliplo;
if((x1 += temp) > xcliphi) { WHEN_OUTSIDE; } WHEN_INSIDE;
y1 = ycliphi; }
WHEN_INSIDE; if( x2 > xcliphi )
} {
if(y2 < ycliplo) temp = USCALE( (y2 - y1), (x2 - xcliphi), (x2 - x1) );
{ y2 -= temp; x2 = xcliphi;
temp = USCALE((x2 - x1),(ycliplo - y2),(y1 - y2)); WHEN_INSIDE;
if((x2 -= temp) < xcliplo) { WHEN_OUTSIDE; } }
y2 = ycliplo; }
WHEN_INSIDE; else
} {
if(x1 < xcliplo) if( (y1 < ycliplo) || (y2 > ycliphi) )
{ {
temp = USCALE((y1 - y2),(xcliplo - x1),(x2 - x1)); WHEN_OUTSIDE;
y1 -= temp; x1 = xcliplo; }
WHEN_INSIDE; if( y1 > ycliphi )
} {
if(x2 > xcliphi) temp = USCALE( (x2 - x1), (y1 - ycliphi), (y1 - y2) );
{ if( (x1 += temp) > xcliphi )
temp = USCALE((y1 - y2),(x2 - xcliphi),(x2 - x1)); {
y2 += temp; x2 = xcliphi; WHEN_OUTSIDE;
WHEN_INSIDE; }
} y1 = ycliphi;
} WHEN_INSIDE;
} while(0); }
if( y2 < ycliplo )
if ( ((x2 + x1)/2 <= xcliphi ) && ((x2+x1)/2 >= xcliplo) \ {
&& ((y2 + y1)/2 <= ycliphi ) && ((y2+y1)/2 >= ycliplo) ) temp = USCALE( (x2 - x1), (ycliplo - y2), (y1 - y2) );
{ if( (x2 -= temp) < xcliplo )
return(BAD_DRC) ; {
} WHEN_OUTSIDE;
}
else return(OK_DRC); y2 = ycliplo;
WHEN_INSIDE;
}
if( x1 < xcliplo )
{
temp = USCALE( (y1 - y2), (xcliplo - x1), (x2 - x1) );
y1 -= temp; x1 = xcliplo;
WHEN_INSIDE;
}
if( x2 > xcliphi )
{
temp = USCALE( (y1 - y2), (x2 - xcliphi), (x2 - x1) );
y2 += temp; x2 = xcliphi;
WHEN_INSIDE;
}
}
} while( 0 );
if( ( (x2 + x1) / 2 <= xcliphi ) && ( (x2 + x1) / 2 >= xcliplo ) \
&& ( (y2 + y1) / 2 <= ycliphi ) && ( (y2 + y1) / 2 >= ycliplo ) )
{
return BAD_DRC;
}
else
return OK_DRC;
} }
...@@ -128,8 +128,7 @@ void WinEDA_PcbFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos ) ...@@ -128,8 +128,7 @@ void WinEDA_PcbFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
#if defined(DEBUG) #if defined(DEBUG)
DrawStruct = m_Pcb->FindPadOrModule( DrawStruct = m_Pcb->FindPadOrModule(
GetScreen()->RefPos(true), GetScreen()->RefPos(true),
GetScreen()->m_Active_Layer, GetScreen()->m_Active_Layer );
VISIBLE_ONLY );
#else #else
DrawStruct = PcbGeneralLocateAndDisplay(); DrawStruct = PcbGeneralLocateAndDisplay();
#endif #endif
......
...@@ -13,10 +13,7 @@ ...@@ -13,10 +13,7 @@
#include "protos.h" #include "protos.h"
/* variables locales */
int ux0, uy0, dx, dy, spot_cX, spot_cY; /* Variables utilisees pour
* la localisation des segments */
/* fonctions locales */ /* fonctions locales */
EDA_BaseStruct* Locate_MirePcb( EDA_BaseStruct* PtStruct, int LayerSearch, int typeloc ); EDA_BaseStruct* Locate_MirePcb( EDA_BaseStruct* PtStruct, int LayerSearch, int typeloc );
...@@ -302,72 +299,21 @@ EDGE_MODULE* Locate_Edge_Module( MODULE* module, int typeloc ) ...@@ -302,72 +299,21 @@ EDGE_MODULE* Locate_Edge_Module( MODULE* module, int typeloc )
* NULL si rien trouve * NULL si rien trouve
*/ */
{ {
EDGE_MODULE* edge_mod;
EDA_BaseStruct* PtStruct;
int uxf, uyf, type_trace;
int rayon, dist;
wxPoint ref_pos; /* coord du point de localisation */
/* pour localisation d'arcs, angle du point de debut, de fin et du point de reference */
int StAngle, EndAngle, MouseAngle;
if( !module ) if( !module )
return NULL; return NULL;
ref_pos = RefPos( typeloc ); /* coord du point de localisation */
wxPoint ref_pos = RefPos( typeloc );
PtStruct = module->m_Drawings; EDA_BaseStruct* PtStruct = module->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext ) for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
{ {
if( PtStruct->m_StructType != TYPEEDGEMODULE ) if( PtStruct->m_StructType != TYPEEDGEMODULE )
continue; continue;
edge_mod = (EDGE_MODULE*) PtStruct; // calls virtual EDGE_MODULE::HitTest()
type_trace = edge_mod->m_Shape; if( PtStruct->HitTest( ref_pos ) )
ux0 = edge_mod->m_Start.x; uy0 = edge_mod->m_Start.y; return (EDGE_MODULE*) PtStruct;
uxf = edge_mod->m_End.x; uyf = edge_mod->m_End.y;
switch( type_trace )
{
case S_SEGMENT:
/* recalcul des coordonnees avec ux0,uy0 = origine des coord. */
spot_cX = ref_pos.x - ux0; spot_cY = ref_pos.y - uy0;
dx = uxf - ux0; dy = uyf - uy0;
/* detection : */
if( distance( edge_mod->m_Width / 2 ) )
return edge_mod;
break;
case S_CIRCLE:
rayon = (int) hypot( (double) (uxf - ux0), (double) (uyf - uy0) );
dist = (int) hypot( (double) (ref_pos.x - ux0), (double) (ref_pos.y - uy0) );
if( abs( rayon - dist ) <= edge_mod->m_Width )
return edge_mod;
break;
case S_ARC:
rayon = (int) hypot( (double) (uxf - ux0), (double) (uyf - uy0) );
dist = (int) hypot( (double) (ref_pos.x - ux0), (double) (ref_pos.y - uy0) );
if( abs( rayon - dist ) > edge_mod->m_Width )
break;
/* pour un arc, controle complementaire */
MouseAngle = (int) ArcTangente( ref_pos.y - uy0, ref_pos.x - ux0 );
StAngle = (int) ArcTangente( uyf - uy0, uxf - ux0 );
EndAngle = StAngle + edge_mod->m_Angle;
if( EndAngle > 3600 )
{
StAngle -= 3600; EndAngle -= 3600;
}
if( (MouseAngle >= StAngle) && (MouseAngle <= EndAngle) )
return edge_mod;
break;
}
} }
return NULL; return NULL;
...@@ -383,105 +329,17 @@ EDA_BaseStruct* Locate_Cotation( BOARD* Pcb, int LayerSearch, int typeloc ) ...@@ -383,105 +329,17 @@ EDA_BaseStruct* Locate_Cotation( BOARD* Pcb, int LayerSearch, int typeloc )
* return a pointer to the located item, or NULL * return a pointer to the located item, or NULL
*/ */
{ {
EDA_BaseStruct* PtStruct; wxPoint ref_pos = RefPos( typeloc );
COTATION* Cotation;
TEXTE_PCB* pt_txt;
wxPoint ref_pos;
int ux0, uy0;
ref_pos = RefPos( typeloc ); EDA_BaseStruct* PtStruct = Pcb->m_Drawings;
PtStruct = Pcb->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext ) for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
{ {
if( PtStruct->m_StructType != TYPECOTATION ) if( PtStruct->m_StructType != TYPECOTATION )
continue; continue;
Cotation = (COTATION*) PtStruct;
if( (Cotation->m_Layer != LayerSearch) && (LayerSearch != -1) )
continue;
/* Localisation du texte ? */
pt_txt = Cotation->m_Text;
if( pt_txt )
{
// because HitTest() is present in both base classes of TEXTE_PCB
// use a dis-ambiguating cast to tell compiler which HitTest()
// to call.
if( static_cast<EDA_TextStruct*>(pt_txt)->HitTest( ref_pos ) )
return PtStruct;
}
/* Localisation des SEGMENTS ?) */
ux0 = Cotation->Barre_ox; uy0 = Cotation->Barre_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = Cotation->Barre_fx - ux0; dy = Cotation->Barre_fy - uy0;
spot_cX = ref_pos.x - ux0; spot_cY = ref_pos.y - uy0;
/* detection : */
if( distance( Cotation->m_Width / 2 ) )
return PtStruct;
ux0 = Cotation->TraitG_ox; uy0 = Cotation->TraitG_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = Cotation->TraitG_fx - ux0; dy = Cotation->TraitG_fy - uy0;
spot_cX = ref_pos.x - ux0; spot_cY = ref_pos.y - uy0;
/* detection : */ // calls virtual COTATION::HitTest()
if( distance( Cotation->m_Width / 2 ) ) if( PtStruct->HitTest( ref_pos ) )
return PtStruct; return (COTATION*) PtStruct;
ux0 = Cotation->TraitD_ox; uy0 = Cotation->TraitD_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = Cotation->TraitD_fx - ux0; dy = Cotation->TraitD_fy - uy0;
spot_cX = ref_pos.x - ux0; spot_cY = ref_pos.y - uy0;
/* detection : */
if( distance( Cotation->m_Width / 2 ) )
return PtStruct;
ux0 = Cotation->FlecheD1_ox; uy0 = Cotation->FlecheD1_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = Cotation->FlecheD1_fx - ux0; dy = Cotation->FlecheD1_fy - uy0;
spot_cX = ref_pos.x - ux0; spot_cY = ref_pos.y - uy0;
/* detection : */
if( distance( Cotation->m_Width / 2 ) )
return PtStruct;
ux0 = Cotation->FlecheD2_ox; uy0 = Cotation->FlecheD2_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = Cotation->FlecheD2_fx - ux0; dy = Cotation->FlecheD2_fy - uy0;
spot_cX = ref_pos.x - ux0; spot_cY = ref_pos.y - uy0;
/* detection : */
if( distance( Cotation->m_Width / 2 ) )
return PtStruct;
ux0 = Cotation->FlecheG1_ox; uy0 = Cotation->FlecheG1_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = Cotation->FlecheG1_fx - ux0; dy = Cotation->FlecheG1_fy - uy0;
spot_cX = ref_pos.x - ux0; spot_cY = ref_pos.y - uy0;
/* detection : */
if( distance( Cotation->m_Width / 2 ) )
return PtStruct;
ux0 = Cotation->FlecheG2_ox; uy0 = Cotation->FlecheG2_oy;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
dx = Cotation->FlecheG2_fx - ux0; dy = Cotation->FlecheG2_fy - uy0;
spot_cX = ref_pos.x - ux0; spot_cY = ref_pos.y - uy0;
/* detection : */
if( distance( Cotation->m_Width / 2 ) )
return PtStruct;
} }
return NULL; return NULL;
...@@ -499,73 +357,32 @@ DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int LayerSearch, int typeloc ) ...@@ -499,73 +357,32 @@ DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int LayerSearch, int typeloc )
* Le segment sur la couche active est dtect en priorite * Le segment sur la couche active est dtect en priorite
*/ */
{ {
EDA_BaseStruct* PtStruct;
DRAWSEGMENT* pts, * locate_segm = NULL;
wxPoint ref_pos;
PCB_SCREEN* screen = (PCB_SCREEN*) ActiveScreen;
ref_pos = RefPos( typeloc ); DRAWSEGMENT* locate_segm = NULL;
PCB_SCREEN* screen = (PCB_SCREEN*) ActiveScreen;
wxPoint ref_pos = RefPos( typeloc );
PtStruct = Pcb->m_Drawings; EDA_BaseStruct* PtStruct = Pcb->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext ) for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
{ {
if( PtStruct->m_StructType != TYPEDRAWSEGMENT ) if( PtStruct->m_StructType != TYPEDRAWSEGMENT )
continue; continue;
pts = (DRAWSEGMENT*) PtStruct;
if( (pts->m_Layer != LayerSearch) && (LayerSearch != -1) )
continue;
ux0 = pts->m_Start.x; uy0 = pts->m_Start.y; DRAWSEGMENT* pts = (DRAWSEGMENT*) PtStruct;
/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */ if( (pts->m_Layer != LayerSearch) && (LayerSearch != -1) )
dx = pts->m_End.x - ux0; dy = pts->m_End.y - uy0; continue;
spot_cX = ref_pos.x - ux0; spot_cY = ref_pos.y - uy0;
/* detection : */ if( pts->HitTest( ref_pos ) )
if( (pts->m_Shape == S_CIRCLE) || (pts->m_Shape == S_ARC) )
{ {
int rayon, dist, StAngle, EndAngle, MouseAngle; // return this hit if layer matches, else remember in
// case no layer match is found.
rayon = (int) hypot( (double) (dx), (double) (dy) ); if( pts->m_Layer == screen->m_Active_Layer )
dist = (int) hypot( (double) (spot_cX), (double) (spot_cY) ); return pts;
if( abs( rayon - dist ) <= (pts->m_Width / 2) )
{
if( pts->m_Shape == S_CIRCLE )
{
if( pts->m_Layer == screen->m_Active_Layer )
return pts;
else if( !locate_segm )
locate_segm = pts;
}
/* pour un arc, controle complementaire */ else if( !locate_segm )
MouseAngle = (int) ArcTangente( spot_cY, spot_cX ); locate_segm = pts;
StAngle = (int) ArcTangente( dy, dx );
EndAngle = StAngle + pts->m_Angle;
if( EndAngle > 3600 )
{
StAngle -= 3600; EndAngle -= 3600;
}
if( (MouseAngle >= StAngle) && (MouseAngle <= EndAngle) )
{
if( pts->m_Layer == screen->m_Active_Layer )
return pts;
else if( !locate_segm )
locate_segm = pts;
}
}
}
else
{
if( distance( pts->m_Width / 2 ) )
{
if( pts->m_Layer == screen->m_Active_Layer )
return pts;
else if( !locate_segm )
locate_segm = pts;
}
} }
} }
...@@ -651,14 +468,6 @@ D_PAD* Locate_Pads( MODULE* module, const wxPoint& ref_pos, int masque_layer ) ...@@ -651,14 +468,6 @@ D_PAD* Locate_Pads( MODULE* module, const wxPoint& ref_pos, int masque_layer )
D_PAD* pt_pad = module->m_Pads; D_PAD* pt_pad = module->m_Pads;
for( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext ) for( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext )
{ {
/*
wxPoint shape_pos = ReturnShapePos();
why the global ux0?
ux0 = shape_pos.x;
uy0 = shape_pos.y; // pos x,y du centre du pad
*/
/* ... et sur la bonne couche */ /* ... et sur la bonne couche */
if( (pt_pad->m_Masque_Layer & masque_layer) == 0 ) if( (pt_pad->m_Masque_Layer & masque_layer) == 0 )
continue; continue;
...@@ -704,8 +513,6 @@ MODULE* Locate_Prefered_Module( BOARD* Pcb, int typeloc ) ...@@ -704,8 +513,6 @@ MODULE* Locate_Prefered_Module( BOARD* Pcb, int typeloc )
if( (typeloc & IGNORE_LOCKED) && pt_module->IsLocked() ) if( (typeloc & IGNORE_LOCKED) && pt_module->IsLocked() )
continue; continue;
/* Localisation: test des dimensions minimales, choix du meilleur candidat */
/* calcul de priorite: la priorite est donnee a la couche /* calcul de priorite: la priorite est donnee a la couche
* d'appartenance du module et a la couche cuivre si le module * d'appartenance du module et a la couche cuivre si le module
* est sur couche serigr,adhesive cuivre, a la couche cmp si le module * est sur couche serigr,adhesive cuivre, a la couche cmp si le module
...@@ -718,6 +525,8 @@ MODULE* Locate_Prefered_Module( BOARD* Pcb, int typeloc ) ...@@ -718,6 +525,8 @@ MODULE* Locate_Prefered_Module( BOARD* Pcb, int typeloc )
else if( layer==ADHESIVE_N_CMP || layer==SILKSCREEN_N_CMP ) else if( layer==ADHESIVE_N_CMP || layer==SILKSCREEN_N_CMP )
layer = CMP_N; layer = CMP_N;
/* Localisation: test des dimensions minimales, choix du meilleur candidat */
/* calcul des dimensions du cadre :*/ /* calcul des dimensions du cadre :*/
lx = pt_module->m_BoundaryBox.GetWidth(); lx = pt_module->m_BoundaryBox.GetWidth();
ly = pt_module->m_BoundaryBox.GetHeight(); ly = pt_module->m_BoundaryBox.GetHeight();
...@@ -998,42 +807,30 @@ TRACK* Locate_Pistes( TRACK* start_adresse, int MasqueLayer, int typeloc ) ...@@ -998,42 +807,30 @@ TRACK* Locate_Pistes( TRACK* start_adresse, int MasqueLayer, int typeloc )
TRACK* Locate_Pistes( TRACK* start_adresse, const wxPoint& ref_pos, int MasqueLayer ) TRACK* Locate_Pistes( TRACK* start_adresse, const wxPoint& ref_pos, int MasqueLayer )
{ {
TRACK* Track; /* pointeur sur les pistes */ for( TRACK* Track = start_adresse; Track; Track = (TRACK*) Track->Pnext )
int l_piste; /* demi-largeur de la piste */
for( Track = start_adresse; Track != NULL; Track = (TRACK*) Track->Pnext )
{ {
if( Track->GetState( BUSY | DELETED ) ) if( Track->GetState( BUSY | DELETED ) )
continue; continue;
if( (g_DesignSettings.m_LayerColor[Track->m_Layer] & ITEM_NOT_SHOW) ) if( (g_DesignSettings.m_LayerColor[Track->m_Layer] & ITEM_NOT_SHOW) )
continue; 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_pos.x - ux0; spot_cY = ref_pos.y - uy0;
if( Track->m_StructType == TYPEVIA ) /* VIA rencontree */ if( Track->m_StructType == TYPEVIA ) /* VIA rencontree */
{ {
if( (abs( spot_cX ) <= l_piste ) && (abs( spot_cY ) <=l_piste) ) if( Track->HitTest( ref_pos ) )
{ return Track;
}
else
{
if( MasqueLayer != -1 )
if( (g_TabOneLayerMask[Track->m_Layer] & MasqueLayer) == 0 )
continue; /* Segments sur couches differentes */
if( Track->HitTest( ref_pos ) )
return Track; return Track;
}
continue;
} }
if( MasqueLayer != -1 )
if( (g_TabOneLayerMask[Track->m_Layer] & MasqueLayer) == 0 )
continue; /* Segments sur couches differentes */
if( distance( l_piste ) )
return Track;
} }
return NULL; return NULL;
} }
...@@ -1065,23 +862,12 @@ TRACK* Locate_Zone( TRACK* start_adresse, int layer, int typeloc ) ...@@ -1065,23 +862,12 @@ TRACK* Locate_Zone( TRACK* start_adresse, int layer, int typeloc )
TRACK* Locate_Zone( TRACK* start_adresse, const wxPoint& ref_pos, int layer ) TRACK* Locate_Zone( TRACK* start_adresse, const wxPoint& ref_pos, int layer )
{ {
TRACK* Zone; /* pointeur sur les pistes */ for( TRACK* Zone = start_adresse; Zone; Zone = (TRACK*) Zone->Pnext )
int l_segm; /* demi-largeur de la piste */
for( Zone = start_adresse; Zone != NULL; Zone = (TRACK*) Zone->Pnext )
{ {
/* 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_pos.x - ux0; spot_cY = ref_pos.y - uy0;
if( (layer != -1) && (Zone->m_Layer != layer) ) if( (layer != -1) && (Zone->m_Layer != layer) )
continue; continue;
if( distance( l_segm ) )
if( Zone->HitTest( ref_pos ) )
return Zone; return Zone;
} }
...@@ -1123,159 +909,6 @@ TEXTE_PCB* Locate_Texte_Pcb( EDA_BaseStruct* PtStruct, int LayerSearch, int type ...@@ -1123,159 +909,6 @@ TEXTE_PCB* Locate_Texte_Pcb( EDA_BaseStruct* PtStruct, int LayerSearch, int type
} }
/*****************************/
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 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( (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;
}
/*******************************************************************************/ /*******************************************************************************/
D_PAD* Fast_Locate_Pad_Connecte( BOARD* Pcb, const wxPoint& ref_pos, int masque_layer ) D_PAD* Fast_Locate_Pad_Connecte( BOARD* Pcb, const wxPoint& ref_pos, int masque_layer )
...@@ -1396,11 +1029,10 @@ EDA_BaseStruct* Locate_MirePcb( EDA_BaseStruct* PtStruct, int LayerSearch, ...@@ -1396,11 +1029,10 @@ EDA_BaseStruct* Locate_MirePcb( EDA_BaseStruct* PtStruct, int LayerSearch,
int typeloc ) int typeloc )
/***********************************************************************/ /***********************************************************************/
/* Serach for a photo target /* Search for a photo target
*/ */
{ {
wxPoint ref_pos;/* coord du point de localisation */ wxPoint ref_pos;/* coord du point de localisation */
int dX, dY, rayon;
if( PtStruct == NULL ) if( PtStruct == NULL )
return NULL; return NULL;
...@@ -1417,13 +1049,10 @@ EDA_BaseStruct* Locate_MirePcb( EDA_BaseStruct* PtStruct, int LayerSearch, ...@@ -1417,13 +1049,10 @@ EDA_BaseStruct* Locate_MirePcb( EDA_BaseStruct* PtStruct, int LayerSearch,
if( LayerSearch != -1 && item->m_Layer != LayerSearch ) if( LayerSearch != -1 && item->m_Layer != LayerSearch )
continue; continue;
dX = ref_pos.x - item->m_Pos.x; if( item->HitTest( ref_pos ) )
dY = ref_pos.y - item->m_Pos.y; break;
rayon = item->m_Size / 2;
if( (abs( dX ) <= rayon ) && ( abs( dY ) <= rayon ) )
break; /* Mire Localisee */
} }
return PtStruct; return PtStruct;
} }
...@@ -198,24 +198,6 @@ D_PAD * Fast_Locate_Pad_Connecte(BOARD * Pcb, const wxPoint & ref_pos, int layer ...@@ -198,24 +198,6 @@ D_PAD * Fast_Locate_Pad_Connecte(BOARD * Pcb, const wxPoint & ref_pos, int layer
(bonne position ET bonne couche). */ (bonne position ET bonne couche). */
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 ( externes 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
*/
TRACK * Locate_Zone(TRACK * start_adresse,int layer, int typeloc); TRACK * Locate_Zone(TRACK * start_adresse,int layer, int typeloc);
TRACK * Locate_Zone(TRACK * start_adresse, const wxPoint & ref_pos,int layer); TRACK * Locate_Zone(TRACK * start_adresse, const wxPoint & ref_pos,int layer);
/* /*
......
...@@ -122,5 +122,5 @@ public: ...@@ -122,5 +122,5 @@ public:
WinEDA_PcbFrame * m_Parent; WinEDA_PcbFrame * m_Parent;
}; };
#endif #endif // _ZONES_H_
// _ZONES_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment