/*
RHINO VERSION ALPHA ___EN CHANTIER___
================================================================================
--- Points d'un petit cercle par triangles Sphériques --- Biname 17mai2021
--------------------------------------------------------------------------------
https://fr.wikipedia.org/wiki/Trigonom%C3%A9trie_sph%C3%A9rique
formule des cosinus, ici alpha=A, beta=B et gamma=C
Origne : Forum
https://forums.futura-sciences.com/mathematiques-superieur/905320-coordonnees
-gps-mille-nautique-cercle-probleme-reel-urgent.html#post6785972
================================================================================
*/
// ========= VARIABLES UTILISATEUR ========
// le 'petit cercle' est l'ensemble des points recherchés
// Latitude du centre du petit cercle (décimales options voir calcul
// !!! Si _deg est negatif, _min et _sec doivent être négatif !!!
// Longitudes EST et LATITUDE SUD sont négatives
// ZWEVER position
var Lat_deg = 47 ; // deg.dddddd
var Lat_min = 9.78 ; // min.dddddd
var Lat_sec = 0 ; // sec.dddddd
// Longitude
var Lon_deg = 2 ; // deg.dddddd
var Lon_min = 25.34 ; // min.dddddd
var Lon_sec = 0 ; // sec.dddddd
// Rayon du cercle
var Rayon = 0.5 ; // Mille Nautique
// nombre de point désirés pour le petit cercle
var nPoint = 12 ;
// ======== FIN VARIABLES UTILISATEUR =====
var PI = Math.PI;
//
// Convertir Latitude et Longitude en deg.ddddddd
// ----------------------------------------------
print ("\nCercle polaire (version alpha 0.001)");
var dLat = Lat_deg + (Lat_min/60) + (Lat_sec/3600);
print(" Latitude Centre = " + dLat.toFixed(5) + "°");
var dLon = Lon_deg + (Lon_min/60) + (Lon_sec/3600);
print(" Longitude Centre = " + dLon.toFixed(5) + "°");
print(" Rayon du petit cercle : " + Rayon + " milles marins");
//
// Vérification de la validité des entrées
// ---------------------------------------
// Latitude <> 0
if(dLat==0){
alert("Latitude can\'t be exactly 0, set to 0.00000001°");
dLat = 0.00000001;
}
// Rayon < 90*60' (moins d'une demi sphère
if(Rayon/60 > 90){
alert("Radius can\'t be greater than 90° or 5400 miles, PGM Stopped Retry");
ERROR_RADIUS_GREATER_THAN_90_DEGREE_OR_5400_MILES_RETRY;
}
// Latitude + Rayon/60 = <90 bug to solve :-)
var dTmp = Math.abs(dLat) + Rayon/60;
if(dTmp > 90){
alert("Latitude + Rayon/60 must be less 90°, PGM Stopped Retry "
+ "\n North and South Poles cannot be in the circle (bug to solve)");
ERROR_LATITUDE_GREATER_THAN_180_DEGREE_RETRY;
}
//
// Calcul des coordonnées des points du cercle
// -------------------------------------------
print ("\nPoints du cercle polaire (" + nPoint +" points)");
// variables globales en radian
var radRay = PI * Rayon/(60 * 180);
var radStep = 2 * PI/nPoint;
var radLat = PI * dLat/180;
var radLon = PI * dLon/180;
var radAlpha;
var offLat, offLon; //off pour offset
var radLat_P, radLon_P;
//
// en radians fonction d'affichage
function printDegMin(alpha, Lat, Lon){
var milCalcRayon = (21600/(2 * PI))*Math.acos(Math.sin(radLat)*Math.sin(radLat_P) +
Math.cos(radLat)*Math.cos(radLat_P)*Math.cos(radLon - radLon_P));
print(" Pt#" + (alpha-180).toPrecision(4) + "°"
+ " Lat: " + parseInt(Lat) + "°"
+ ( (Lat - parseInt(Lat))*60 ).toFixed(3) + "'"
+ " Lon: " + parseInt(Lon) + "°"
+ ( (Lon - parseInt(Lon))*60 ).toFixed(3) + "'"
+ " ||"
+ " Lat:" + Lat.toFixed(5) + "°"
+ " Lon:" + Lon.toFixed(5) + "°"
//+ " offLon=" + (180*offLon/PI).toFixed(5) + "°"
+ " || Err_Rayon="
+ " " + (-Rayon + milCalcRayon).toPrecision(3)
+ " CalcRayon=" + milCalcRayon.toFixed(3)
);
}
//
for(radAlpha=PI; radAlpha<= 3*PI+0.000001; radAlpha+=radStep){ // +0.000001 to get 3PI]
// soit le triangle sphérique ABC (pour coller avec les formules de TrigSphé)
// A le centre du petit cercle, B projection de A sur l'équateur,
// C un point du petit cercle recherché
// !!!! attention case sensitive : C <> c, A <> a et B <> b !!!!
// on a : b = Rayon du petit cercle, c = Latitude de centre du petit cercle
// A = on le fait varier de 0 à 360° au pas choisi (nommé radAlpha ici)
// cos a = cos b * cos c + sin b * sin c * cos A formule trig sphé
var a;
// if for case cos(radAlpha) = 0
// if(radAlpha==PI/2||radAlpha==3*PI/2) {a = Math.acos(Math.cos(radRay)*Math.cos(radLat))}
// else {
a = Math.acos(Math.cos(radRay)*Math.cos(radLat) + Math.sin(radRay)*Math.sin(radLat)*Math.cos(radAlpha))
//};
// cos c = cos a * cos b + sin a * sin b * cos C formule trig sphé
var C = Math.acos((Math.cos(radLat) - Math.cos(a) * Math.cos(radRay))/(Math.sin(a)*Math.sin(radRay)));
var B = Math.acos((Math.cos(radRay) - Math.cos(radLat) * Math.cos(a))/(Math.sin(radLat)*Math.sin(a)));
if (radAlpha==PI || radAlpha==2*PI)
{print (
"debug a=" + a +
" C=" + C +
" B=" + B) };
//
// Soit un second triangle sphérique AA_CC_BB, AA est la projection de C sur l'équateur,
// BB est le même point que B et CC le même point que C
// on connait aa = a désolé :-), BB = 90 - B = PI/2 - B
var BB = (PI/2) - B;
// ce triangle est rectangle en AA
// dans un triangle sphérique rectangle en A on a
// sin b = sin a * sin B
var bb = Math.asin(Math.sin(a) * Math.sin(BB));
radLat_P = bb;
//
// on a aussi
// cotg a = cotg c * cos B mais yapas cotangente et encore moins arc cotangente en JS,
// gépeucherché, on va passer en tangente cotg a = 1 / tg a
// 1 / ta a = cos B / tg c ou
// tg a = tg c / cos B ((on se demande ??? cours 1970?? signe ??))
// tg c = tg a * cos B
var cc = Math.atan(Math.tan(a) * Math.cos(BB));
offLon = cc;
// gère le signe probablement perdu en passant de cotg à tg ???
if (radAlpha < 2*PI){offLon=-offLon};
radLon_P = radLon + offLon;
printDegMin(180*radAlpha/PI, 180*radLat_P/PI, 180*radLon_P/PI);
}
// warnings and Finished
print("\n\n Check : Last point is the same point as point #0");
print("\n\n SAUF ERREURSSSSS :-) *** FINISHED ***");