import { ShapesFactory } from "./olqv_shapes.js";
import { FITS_HEADER } from "./fitsheader.js";
import {DecDeg2DMS, DecDeg2HMS} from "./utils.js";
/**
*
* @typedef {Object} AxesFactory
* @extends ShapesFactory
*
* @property {number} numeridians number of visible meridians (int)
* @property {number} nparallels number of visible parallels (int)
* @property {number} cdelt1 cdelt1 in radians (header is in degrees) (float)
* @property {number} cdelt2 cdelt2 in radians (header is in degrees) (float)
* @property {object} axisStyle styling options for axis
*/
class AxesFactory extends ShapesFactory {
static enter(what) {
console.group(this.name + "." + what);
}
static exit() {
console.groupEnd();
}
/**
*
* @param {Viewer} viewer
*/
constructor(viewer) {
super(viewer, 'axes');
this.numeridians = 4;
this.nparallels = 4;
// number of decimals for ra/dec values on axis
//this._displayedDecimals = Math.abs(FITS_HEADER.cdelt1).toExponential().split("-")[1] - 1;
// cdelt1 in radians
this.cdelt1 = FITS_HEADER.cdelt1 * Math.PI / 180;
//cdelt2 in radians
this.cdelt2 = FITS_HEADER.cdelt2 * Math.PI / 180;
this.axisStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'green',
width: 2,
}),
});
}
/**
* Traces axes on image
*/
build() {
let axes = this.getAxes();
let lineString = new ol.geom.MultiLineString(axes);
let f = new ol.Feature({ geometry: lineString.simplify(1) });
f.setStyle(this.axisStyle);
this.layer.setZIndex(10);
this.layer.getSource().addFeature(f);
for (let i = 0; i < axes.length; i++) {
this.addExtremityPoint(axes[i][0]);
this.addExtremityPoint(axes[i][axes[i].length - 1]);
}
this.layer.set('axes', "axes");
this.layer.changed();
}
/**
* Shows coordinates at both axis extremity
* @param {array} ra/dec coordinates
*/
addExtremityPoint(coords) {
let radec = this.projection.iRaiDecToRaDec(coords[0], coords[1]);
let point = new ol.geom.Point(coords);
let f2 = new ol.Feature({ geometry: point });
f2.setStyle(new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'green',
width: 10,
}),
text: new ol.style.Text({
font: '12px Calibri,sans-serif',
fill: new ol.style.Fill({ color: '#000' }),
stroke: new ol.style.Stroke({
color: '#fff',
width: 2
}),
// get the text from the feature - `this` is ol.Feature
// and show only under certain resolution
text: "RA : " + DecDeg2HMS(radec['ra']) + ", DEC : " + DecDeg2DMS(radec['dec'])
//text: "RA : " + radec['ra'].toFixed(this._displayedDecimals) + ", DEC : " + radec['dec'].toFixed(this._displayedDecimals)
})
}));
this.layer.getSource().addFeature(f2);
}
/**
* Returns the points defining the meridians curves. The result curves will be smoothed before display.
* @param {array} ra/dec limit values
* @returns {array} an array of x, y arrays with all coordinates of the meridians
*/
getMeridians(limits) {
// Plot the meridians,
const dra = (limits["RA_max"] - limits["RA_min"]) / (this.numeridians - 1);
let decs = [];
for (let i = 0; i < FITS_HEADER.naxis2; i++) {
decs.push(limits["DEC_min"] + i * (limits["DEC_max"] - limits["DEC_min"]) / (FITS_HEADER.naxis2 - 1));
}
let coordinates_list = [];
for (let i = 0; i < this.numeridians; i++) {
let coordinates = [];
let ra_ = limits["RA_min"] + i * dra;
if(i==0){
console.log("ra_" + ra_);
}
for (let j = 0; j < FITS_HEADER.naxis2; j++) {
let xy = this.projection.absToRel([ra_], [decs[j]]);
const i_xp = Math.round(FITS_HEADER.crpix1 + (xy['x'][0]) / (this.cdelt1) - 1);
const i_yp = Math.round(FITS_HEADER.crpix2 + (xy['y'][0]) / (this.cdelt2) - 1);
if (this.viewer.isInExtent(i_xp, i_yp)) {
coordinates.push([i_xp, i_yp]);
}
}
if (coordinates.length > 1)
coordinates_list.push(coordinates);
}
return coordinates_list;
}
/**
* Returns the points defining the parallels curves. The result curves will be smoothed before display.
* @param {object} ra/dec limit values
* @returns {array} an array of x, y arrays with all coordinates of the parallels
*/
getParallels(limits) {
const ddec = (limits["DEC_max"] - limits["DEC_min"]) / (this.nparallels);
let ras = [];
for (let i = 0; i < FITS_HEADER.naxis1; i++) {
ras.push(limits["RA_min"] + i * (limits["RA_max"] - limits["RA_min"]) / (FITS_HEADER.naxis1 - 1))
}
let coordinates_list = [];
for (let i = 0; i < this.nparallels; i++) {
let coordinates = [];
let ixpix = [];
let iypix = [];
let dec_ = limits["DEC_min"] + i * ddec;
if(i==0){
console.log("dec_" + dec_);
}
for (let j = 0; j < FITS_HEADER.naxis1; j++) {
let xy = this.projection.absToRel([ras[j]], [dec_]);
const i_xp = Math.round(FITS_HEADER.crpix1 + (xy['x'][0]) / (this.cdelt1) - 1);
const i_yp = Math.round(FITS_HEADER.crpix2 + (xy['y'][0]) / (this.cdelt2) - 1);
ixpix.push(i_xp);
iypix.push(i_yp);
if (this.viewer.isInExtent(i_xp, i_yp)) {
coordinates.push([i_xp, i_yp]);
}
if (coordinates.length > 1)
coordinates_list.push(coordinates);
}
}
return coordinates_list;
}
/**
* Returns the boundaries of ra/dec values
* @returns {object}
*/
getLimits() {
let result = { "RA_min": 0, "RA_max": 0, "DEC_min": 0, "DEC_max": 0 };
let x = new Array(FITS_HEADER.naxis1).fill(0);
let y = new Array(FITS_HEADER.naxis2).fill(0);
// coordinates after projection
let raDec;
for (let i = 0; i < FITS_HEADER.naxis1; i++) {
x[i] = (i - FITS_HEADER.crpix1) * this.cdelt1;
}
for (let j = 0; j < FITS_HEADER.naxis2; j++) {
y[j] = (j - FITS_HEADER.crpix2) * this.cdelt2;
}
raDec = this.projection.relToAbs([x[0]], [y[0]]);
result = { "RA_min": raDec['ra'][0],
"RA_max": raDec['ra'][0],
"DEC_min": raDec['dec'][0],
"DEC_max": raDec['dec'][0] };
let ra = new Array(x.length);
let dec = new Array(x.length);
for (var i = 0; i < x.length; i++){
ra[i] = new Array(y.length);
dec[i] = new Array(y.length);
}
for (let i = 0; i < x.length; i++) {
for (let j = 0; j < y.length; j++) {
raDec = this.projection.relToAbs([x[i]], [y[j]]);
ra[i][j]=raDec['ra'][0];
dec[i][j]=raDec['dec'][0];
if (ra[i][j] < result["RA_min"]) {
result["RA_min"] = ra[i][j];
}
if (ra[i][j] > result["RA_max"]) {
result["RA_max"] = ra[i][j];
}
if (dec[i][j] < result["DEC_min"]) {
result["DEC_min"] = dec[i][j];
}
if (dec[i][j] > result["DEC_max"]) {
result["DEC_max"] = dec[i][j];
}
}
}
return result;
}
/**
* Returns a list of corrdinates of point defining parallels and meridians
* @returns {array}
*/
getAxes() {
let limits = this.getLimits();
// Plot the meridians
let coordinates_list = this.getMeridians(limits);
let parallels = this.getParallels(limits);
coordinates_list.push.apply(coordinates_list, parallels);
//return multipoints;
return coordinates_list;
}
}
export {
AxesFactory
}