This repository has been archived on 2023-11-03. You can view files and clone it, but cannot push or open issues or pull requests.
GINPA/Modele/calcul.c

206 lines
4.8 KiB
C

#include "calcul.h"
double distance(Coordonnees const* const a, Coordonnees const* const b)
{
/* Conversion des latitudes & longitudes en radians */
const double latA = RADIANS(a->lat);
const double latB = RADIANS(b->lat);
const double lonA = RADIANS(a->lon);
const double lonB = RADIANS(b->lon);
const double arg = sqrt(pow(sin((latA - latB) / 2), 2) + cos(latA) * cos(latB) * pow(sin((lonA - lonB) / 2), 2));
return 2 * RAYON * asin(arg);
}
void redresserRectangle(sfVector2f *const positionHG, sfVector2f *const positionBD, const bool carre)
{
const sfVector2f point1 = *positionHG;
const sfVector2f point2 = *positionBD;
if((point2.x > point1.x) && (point2.y < point1.y))
{
positionHG->y = point2.y;
positionBD->y = point1.y;
}
else if(point2.x < point1.x)
{
if(point2.y < point1.y)
{
*positionHG = point2;
*positionBD = point1;
}
else
{
positionHG->x = point2.x;
positionBD->x = point1.x;
}
}
// Si l'on souhaite avoir un carré à la place d'un rectangle, on récupère la dimension du côté qui est maximale, et on la fixe sur les deux dimensions
if(carre)
{
int32_t moitLongestSide = 0;
int32_t lAbscisse = positionBD->x - positionHG->x;
int32_t lOrdonnee = positionBD->y - positionHG->y;
if(lAbscisse > lOrdonnee)
{
moitLongestSide = lAbscisse/2;
positionHG->y = positionHG->y + lOrdonnee/2 - moitLongestSide;
positionBD->y = positionHG->y + moitLongestSide*2;
positionBD->x = positionHG->x + moitLongestSide*2;
if(positionHG->y < 0)
{
positionBD->y = moitLongestSide*2+1;
positionHG->y = 1;
}
}
else
{
moitLongestSide = lOrdonnee/2;
positionHG->x = positionHG->x + lAbscisse/2 - moitLongestSide;
positionBD->x = positionHG->x + moitLongestSide*2;
positionBD->y = positionHG->y + moitLongestSide*2;
if(positionHG->x < 0)
{
positionBD->x = moitLongestSide*2+1;
positionHG->x = 1;
}
}
}
}
time_t temps(const Point a, const Point b)
{
if(a.date <= b.date)
return b.date - a.date;
return a.date - b.date;
}
double percentPointsInCercle(Point const * const points, const uint32_t taille, Coordonnees const * const centre, const double rayon)
{
uint32_t in = 0;
for(uint32_t i=0;i < taille;i++)
{
if(distance(&points[i].pos, centre) <= rayon)
in++;
}
return 1.0 * in / taille;
}
void getExtrema(Point const* const pts, uint32_t const taille, Coordonnees *const hautGauche, Coordonnees *const basDroit)
{
double lonOuestDroite=-181;
double lonOuestGauche=1;
double lonEstDroite=-1;
double lonEstGauche=181;
basDroit->lat = 90;
hautGauche->lat = -90;
for(uint32_t i = 0; i < taille; i++)
{
if (pts[i].pos.lon < 0)
{
if(lonOuestDroite < pts[i].pos.lon)
{
lonOuestDroite = pts[i].pos.lon;
}
if(lonOuestGauche > pts[i].pos.lon)
{
lonOuestGauche = pts[i].pos.lon;
}
}
else
{
if(lonEstDroite < pts[i].pos.lon)
{
lonEstDroite=pts[i].pos.lon;
}
if(lonEstGauche > pts[i].pos.lon)
{
lonEstGauche=pts[i].pos.lon;
}
}
if(basDroit->lat > pts[i].pos.lat)
{
basDroit->lat = pts[i].pos.lat;
}
if(hautGauche->lat < pts[i].pos.lat)
{
hautGauche->lat = pts[i].pos.lat;
}
}
if(lonOuestDroite == -181)
{
hautGauche->lon = lonEstGauche;
basDroit->lon = lonEstDroite;
}
else if(lonEstGauche == 181)
{
hautGauche->lon = lonOuestGauche;
basDroit->lon = lonOuestDroite;
}
else if(360 - lonEstGauche + lonOuestDroite < lonEstDroite - lonOuestGauche)
{
hautGauche->lon = lonEstGauche;
basDroit->lon = lonOuestDroite;
}
else
{
hautGauche->lon = lonOuestGauche;
basDroit->lon = lonEstDroite;
}
}
inline uint8_t getZoomFromMaxRatio(const double maxRatio)
{
int8_t zoom = floor(log2(CONSTANTE / maxRatio) - 1);
return (zoom > ZOOMAX ? ZOOMAX : (zoom < ZOOMIN ? ZOOMIN : zoom));
}
inline double getEchelleFromZoom(const uint8_t zoom)
{
return (CONSTANTE / pow(2.0, zoom + 1));
}
void getZoomEchelle(Carte *const carte)
{
/*
Explications:
`carte` pointe sur une structure dont les champs correspondant aux points HG et BD sont remplis et corrects.
Il "suffit" maintenant de déterminer l'échelle et le zoom les plus adaptés pour cette vue.
Pour cela on calcule un rapport qui représente la distance maximale qui est à afficher sur notre carte (dont les dimensions sont connues au préalable).
Ce rapport est directement donné à une des deux fonctions ci-dessus qui détermine le meilleur zoom.
De ce zoom on en déduit ensuite l'échelle RÉELLE de la carte qui sera téléchargée et affichée.
*/
// Voir calculs (dans le corps des fonctions ci-dessus) pour les deux appels suivants:
carte->zoom = getZoomFromMaxRatio(distance(&carte->pointHautGauche, &carte->pointBasDroite) * (1 + EXTRADISTANCEPERCENTAGE / 100.0) / (1.0e-2 * MAPSIZE * MAPSCALE / PPCM));
carte->echelle = getEchelleFromZoom(carte->zoom);
}