mirror of
https://github.com/eddyem/small_tel.git
synced 2025-12-06 10:45:16 +03:00
213 lines
6.3 KiB
C
213 lines
6.3 KiB
C
/*
|
|
* This file is part of the uniformdistr project.
|
|
* Copyright 2022 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <usefull_macros.h>
|
|
|
|
#include "uniform.h"
|
|
|
|
static double Zmin, Zmax;
|
|
|
|
typedef enum{
|
|
SORT_NONE,
|
|
SORT_POS,
|
|
SORT_NEG,
|
|
SORT_AMOUNT
|
|
} t_sorting;
|
|
|
|
typedef struct{
|
|
const char *alg;
|
|
const char *help;
|
|
} strpair;
|
|
|
|
static const strpair sorthelp[SORT_AMOUNT] = {
|
|
[SORT_NONE] = {"none", "don't sort"},
|
|
[SORT_POS] = {"positive", "sort in increasing order"},
|
|
[SORT_NEG] = {"negative", "sort in decreasing order"},
|
|
};
|
|
|
|
typedef enum{
|
|
COORD_A,
|
|
COORD_Z,
|
|
COORD_HA,
|
|
COORD_DEC,
|
|
COORD_AMOUNT
|
|
} t_coord;
|
|
|
|
static const char *coordname[COORD_AMOUNT] = {
|
|
[COORD_A] = "A",
|
|
[COORD_Z] = "Z",
|
|
[COORD_HA] = "HA",
|
|
[COORD_DEC] = "DEC"
|
|
};
|
|
|
|
// convert angle in radians into 0..360 degrees
|
|
static double deg360(double rad){
|
|
rad *= 180. / M_PI;
|
|
int n = (int)(rad / 360.);
|
|
rad -= 360. * n;
|
|
if(rad < 0.) rad += 360.;
|
|
return rad;
|
|
}
|
|
|
|
// convert angle in radians into -180..180 degrees
|
|
static double deg180(double rad){
|
|
rad = deg360(rad);
|
|
if(rad > 180.) rad -= 360.;
|
|
return rad;
|
|
}
|
|
|
|
// compare coordinates - for sorting
|
|
static int spos(double a1, double a2){
|
|
if(a1 > a2) return 1;
|
|
else return -1;
|
|
}
|
|
static int sneg(double a1, double a2){
|
|
if(a1 < a2) return 1;
|
|
else return -1;
|
|
}
|
|
// default compare functions
|
|
static int (*compf)(const void *, const void *) = NULL;
|
|
// compare points - for sorting
|
|
static int compapos(const void *a1, const void *a2){
|
|
return spos(((point*)a1)->A, ((point*)a2)->A);
|
|
}
|
|
static int companeg(const void *a1, const void *a2){
|
|
return sneg(((point*)a1)->A, ((point*)a2)->A);
|
|
}
|
|
static int compzpos(const void *a1, const void *a2){
|
|
return spos(((point*)a1)->Z, ((point*)a2)->Z);
|
|
}
|
|
static int compzneg(const void *a1, const void *a2){
|
|
return sneg(((point*)a1)->Z, ((point*)a2)->Z);
|
|
}
|
|
static int comphapos(const void *a1, const void *a2){
|
|
return spos(((point*)a1)->HA, ((point*)a2)->HA);
|
|
}
|
|
static int comphaneg(const void *a1, const void *a2){
|
|
return sneg(((point*)a1)->HA, ((point*)a2)->HA);
|
|
}
|
|
static int compdecpos(const void *a1, const void *a2){
|
|
return spos(((point*)a1)->Dec, ((point*)a2)->Dec);
|
|
}
|
|
static int compdecneg(const void *a1, const void *a2){
|
|
return sneg(((point*)a1)->Dec, ((point*)a2)->Dec);
|
|
}
|
|
|
|
static int (*comparray[COORD_AMOUNT][SORT_AMOUNT])(const void *, const void *) = {
|
|
[COORD_A] = {[SORT_NONE] = NULL, [SORT_POS] = compapos, [SORT_NEG] = companeg},
|
|
[COORD_Z] = {[SORT_NONE] = NULL, [SORT_POS] = compzpos, [SORT_NEG] = compzneg},
|
|
[COORD_HA] = {[SORT_NONE] = NULL, [SORT_POS] = comphapos, [SORT_NEG] = comphaneg},
|
|
[COORD_DEC] = {[SORT_NONE] = NULL, [SORT_POS] = compdecpos, [SORT_NEG] = compdecneg},
|
|
};
|
|
|
|
// convert horizontal to equatorial
|
|
static void hor2eq(point *p){
|
|
double alt_s, alt_c, A_s, A_c; // sin/cos of alt and Az
|
|
sincos((90. - p->Z)*M_PI/180., &alt_s, &alt_c);
|
|
sincos(p->A*M_PI/180., &A_s, &A_c);
|
|
double sind = SIN_LAT_OBS * alt_s + COS_LAT_OBS * alt_c * A_c;
|
|
double d = asin(sind), cosd = cos(d);
|
|
p->Dec = d *180./M_PI;
|
|
double x = (alt_s - sind * SIN_LAT_OBS) / (cosd * COS_LAT_OBS);
|
|
double y = -A_s * alt_c / cosd;
|
|
p->HA = atan2(y, x) *180./M_PI;
|
|
if(p->HA < 0.) p->HA += 360.;
|
|
}
|
|
|
|
/**
|
|
* @brief getHpoints - calculate equally distributed points A/Z (degrees)
|
|
* @param N (io) - max number of points (i), actual number of points (o)
|
|
* @return array of unsorted coordinates
|
|
*/
|
|
static point* getHpoints(int *N){
|
|
if(!N || *N < 1) return NULL;
|
|
int n = *N, total = 0;
|
|
point* points = MALLOC(point, n), *pptr = points;
|
|
double ang = M_PI * (1. + sqrt(5));
|
|
for(int i = 0; i < n; ++i){
|
|
// we need only one hemisphere, so instead of acos(1. - 2.*(i+0.5)/n) get
|
|
double phi = acos(1. - (i+0.5)/n);
|
|
double theta = ang * i;
|
|
//DBG("phi = %g (%g), theta = %g (%g)", phi, deg360(phi), theta, deg360(theta));
|
|
if(phi > M_PI_2) break;
|
|
double Z = deg360(phi);
|
|
if(Z < Zmin || Z > Zmax) continue;
|
|
++total;
|
|
pptr->A = deg180(theta);
|
|
pptr->Z = Z;
|
|
//BG("%d:\t%g / %g", total, pptr->A, pptr->Z);
|
|
++pptr;
|
|
}
|
|
*N = total;
|
|
return points;
|
|
}
|
|
|
|
int set_Zlimits(double minz, double maxz){
|
|
if(minz > 80. || minz < 0.) return FALSE;
|
|
if(maxz > 90. || maxz < 10.) return FALSE;
|
|
Zmin = minz;
|
|
Zmax = maxz;
|
|
return TRUE;
|
|
}
|
|
|
|
point *getPoints(int *N){
|
|
point *points = getHpoints(N);
|
|
if(!points) return NULL;
|
|
// convert A,Z -> Ha,Dec (if sorting by HA/Dec?)
|
|
for(int i = 0; i < *N; ++i)
|
|
hor2eq(&points[i]);
|
|
if(compf){ // sort data
|
|
DBG("sort");
|
|
qsort(points, *N, sizeof(point), compf);
|
|
}
|
|
return points;
|
|
}
|
|
|
|
// set sorting parameters
|
|
int set_sorting(char *param, char *coord){
|
|
DBG("Try to set sorting '%s' by '%s'", param, coord);
|
|
int x = 0, c = 0;
|
|
for(; c < COORD_AMOUNT; ++c){
|
|
if(strcasecmp(coordname[c], coord) == 0) break;
|
|
}
|
|
if(c == COORD_AMOUNT) return FALSE;
|
|
for(; x < SORT_AMOUNT; ++x){
|
|
//DBG("x=%d, cmp %s %s", x, sorthelp[x].alg, param);
|
|
if(strncmp(param, sorthelp[x].alg, strlen(param)) == 0) break;
|
|
}
|
|
if(x == SORT_AMOUNT) return FALSE;
|
|
DBG("x=%d, c=%d", x,c);
|
|
compf = comparray[c][x];
|
|
return TRUE;
|
|
}
|
|
|
|
void show_sorting_help(){
|
|
fprintf(stderr, "Sorting algorythms:\n");
|
|
for(int i = 0; i < SORT_AMOUNT; ++i){
|
|
fprintf(stderr, "\t%s - %s\n", sorthelp[i].alg, sorthelp[i].help);
|
|
}
|
|
fprintf(stderr, "Sorting coordinates:\n");
|
|
for(int i = 0; i < COORD_AMOUNT; ++i){
|
|
fprintf(stderr, "\t%s\n", coordname[i]);
|
|
}
|
|
}
|