400 lines
10 KiB
C++
400 lines
10 KiB
C++
/************************/
|
|
/* Routines de rotation */
|
|
/************************/
|
|
|
|
/* Fichier TRIGO.CPP */
|
|
|
|
#include "fctsys.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( (double) segY, (double) segX ) * 1800 / M_PI);
|
|
cXrot = pointX; cYrot = pointY;
|
|
|
|
RotatePoint( &cXrot, &cYrot, angle ); /* Rotation du point a tester */
|
|
RotatePoint( &segX, &segY, angle ); /* Rotation du segment */
|
|
|
|
/* la piste est Horizontale , par suite des modifs de coordonnes
|
|
* et d'axe, donc segX = longueur du segment */
|
|
|
|
if( abs( cYrot ) <= seuil ) /* ok sur axe vertical) */
|
|
{
|
|
if( (cXrot >= 0) && (cXrot <= segX) )
|
|
return 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 )
|
|
/***********************************/
|
|
|
|
/* Retourne l'arc tangente en 0.1 degres du vecteur de coord dx, dy
|
|
* entre -1800 et 1800
|
|
* Analogue a atan2 ( mais plus rapide pour les calculs si
|
|
* l'angle est souvent 0, -1800, ou +- 900
|
|
*/
|
|
{
|
|
double fangle;
|
|
|
|
if( dy == 0 )
|
|
{
|
|
if( dx >= 0 )
|
|
return 0;
|
|
else
|
|
return -1800;
|
|
}
|
|
|
|
if( dx == 0 )
|
|
{
|
|
if( dy >= 0 )
|
|
return 900;
|
|
else
|
|
return -900;
|
|
}
|
|
|
|
if( dx == dy )
|
|
{
|
|
if( dx >= 0 )
|
|
return 450;
|
|
else
|
|
return -1800 + 450;
|
|
}
|
|
|
|
if( dx == -dy )
|
|
{
|
|
if( dx >= 0 )
|
|
return -450;
|
|
else
|
|
return 1800 - 450;
|
|
}
|
|
|
|
fangle = atan2( (double) dy, (double) dx ) / M_PI * 1800;
|
|
return (int) round( fangle );
|
|
}
|
|
|
|
|
|
/*********************************************/
|
|
void RotatePoint( int* pX, int* pY, int angle )
|
|
/*********************************************/
|
|
|
|
/*
|
|
* Fonction surchargee!
|
|
* calcule les nouvelles coord du point de coord pX, pY,
|
|
* pour une rotation de centre 0, 0, et d'angle angle ( en 1/10 degre)
|
|
*/
|
|
{
|
|
double fpx, fpy;
|
|
int tmp;
|
|
|
|
while( angle < 0 )
|
|
angle += 3600;
|
|
|
|
while( angle >= 3600 )
|
|
angle -= 3600;
|
|
|
|
if( angle == 0 )
|
|
return;
|
|
|
|
/* Calcul des coord :
|
|
* coord: xrot = y*sin + x*cos
|
|
* yrot = y*cos - x*sin
|
|
*/
|
|
if( angle == 900 ) /* sin = 1, cos = 0 */
|
|
{
|
|
tmp = *pX;
|
|
*pX = *pY;
|
|
*pY = -tmp;
|
|
}
|
|
else if( angle == 1800 ) /* sin = 0, cos = -1 */
|
|
{
|
|
*pX = -*pX;
|
|
*pY = -*pY;
|
|
}
|
|
else if( angle == 2700 ) /* sin = -1, cos = 0 */
|
|
{
|
|
tmp = *pX;
|
|
*pX = -*pY;
|
|
*pY = tmp;
|
|
}
|
|
else
|
|
{
|
|
fpx = (*pY * fsinus[angle]) + (*pX * fcosinus[angle]);
|
|
fpy = (*pY * fcosinus[angle]) - (*pX * fsinus[angle]);
|
|
|
|
*pX = (int) round( fpx );
|
|
*pY = (int) round( fpy );
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************/
|
|
void RotatePoint( int* pX, int* pY, int cx, int cy, int angle )
|
|
/*************************************************************/
|
|
|
|
/*
|
|
* Fonction surchargee!
|
|
* calcule les nouvelles coord du point de coord pX, pY,
|
|
* pour une rotation de centre cx, cy, et d'angle angle ( en 1/10 degre)
|
|
*/
|
|
{
|
|
int ox, oy;
|
|
|
|
ox = *pX - cx;
|
|
oy = *pY - cy;
|
|
|
|
RotatePoint( &ox, &oy, angle );
|
|
|
|
*pX = ox + cx;
|
|
*pY = oy + cy;
|
|
}
|
|
|
|
|
|
/********************************************/
|
|
void RotatePoint( wxPoint* point, int angle )
|
|
/********************************************/
|
|
|
|
/*
|
|
* Fonction surchargee!
|
|
* calcule les nouvelles coord du point point,
|
|
* pour une rotation d'angle angle ( en 1/10 degre)
|
|
*/
|
|
{
|
|
int ox, oy;
|
|
|
|
ox = point->x;
|
|
oy = point->y;
|
|
|
|
RotatePoint( &ox, &oy, angle );
|
|
point->x = ox;
|
|
point->y = oy;
|
|
}
|
|
|
|
|
|
/*****************************************************************/
|
|
void RotatePoint( wxPoint* point, const wxPoint& centre, int angle )
|
|
/*****************************************************************/
|
|
|
|
/*
|
|
* Fonction surchargee!
|
|
* calcule les nouvelles coord du point point,
|
|
* pour une rotation de centre centre, et d'angle angle ( en 1/10 degre)
|
|
*/
|
|
{
|
|
int ox, oy;
|
|
|
|
ox = point->x - centre.x;
|
|
oy = point->y - centre.y;
|
|
|
|
RotatePoint( &ox, &oy, angle );
|
|
point->x = ox + centre.x;
|
|
point->y = oy + centre.y;
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
void RotatePoint( double* pX, double* pY, double cx, double cy, int angle )
|
|
/*************************************************************************/
|
|
{
|
|
double ox, oy;
|
|
|
|
ox = *pX - cx;
|
|
oy = *pY - cy;
|
|
|
|
RotatePoint( &ox, &oy, angle );
|
|
|
|
*pX = ox + cx;
|
|
*pY = oy + cy;
|
|
}
|
|
|
|
|
|
/*************************************************/
|
|
void RotatePoint( double* pX, double* pY, int angle )
|
|
/*************************************************/
|
|
|
|
/* Calcul des coord :
|
|
* coord: xrot = y*sin + x*cos
|
|
* yrot = y*cos - x*sin
|
|
*/
|
|
{
|
|
double tmp;
|
|
|
|
while( angle < 0 )
|
|
angle += 3600;
|
|
|
|
while( angle >= 3600 )
|
|
angle -= 3600;
|
|
|
|
if( angle == 0 )
|
|
return;
|
|
|
|
if( angle == 900 ) /* sin = 1, cos = 0 */
|
|
{
|
|
tmp = *pX;
|
|
*pX = *pY;
|
|
*pY = -tmp;
|
|
}
|
|
else if( angle == 1800 ) /* sin = 0, cos = -1 */
|
|
{
|
|
*pX = -*pX;
|
|
*pY = -*pY;
|
|
}
|
|
else if( angle == 2700 ) /* sin = -1, cos = 0 */
|
|
{
|
|
tmp = *pX;
|
|
*pX = -*pY;
|
|
*pY = tmp;
|
|
}
|
|
else
|
|
{
|
|
double fpx = (*pY * fsinus[angle]) + (*pX * fcosinus[angle]);
|
|
double fpy = (*pY * fcosinus[angle]) - (*pX * fsinus[angle]);
|
|
|
|
*pX = fpx;
|
|
*pY = fpy;
|
|
}
|
|
}
|
|
|
|
|