/*
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
*/
import Enum from 'enum';
import numeral from 'numeral';
import {logError} from '../util/WebUtil.js';
import {getPixScaleArcSec, PlotAttribute, isImage} from './WebPlot.js';
import {primePlot, getFoV} from './PlotViewUtil.js';
import VisUtil from './VisUtil.js';
export const levels= [.03125, .0625, .125,.25,.5, .75, 1,2,3, 4,5, 6, 7,8, 9, 10, 11, 12, 13, 14, 15, 16, 32];
// const hiPSLevelsOLD= [0.000000007445312,
// 0.00000000930664,
// 0.000000011167969,
// 0.00000002978125,
// 0.0000000595625,
// 0.000000119125,
// 0.00000357421875, 0.00000023825, 0.0000004765, 0.000000953,0.000001906,
// 0.0000038125, 0.000002859375, 0.000007625, 0.00001525, 0.0000305,
// 0.0000610, 0.000122070, 0.000244140625, 0.00048828125,
// 0.0009765625, .001953125, 0.00390625, .0078125,
// .015625, .03125, .0625, .125,.25, .5, .75, 1,2, 4, 8, 10,
// 14, 16, 32, 64, 128, 256, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192,
// 10240, 16364, 24556, 32728, 57284, 65456, 122740, 130928 ];
const hiPSLevels= (()=> {
const upMax= 3;
const downMax= 62;
const up= [1];
const down= [];
down[downMax]= .75;
for(let i=1; i<upMax; i++) up[i]= up[i-1] * 1.5;
for(let j=downMax-1; j>=0; j--) down[j]= down[j+1]*.75;
return [...down, ...up];
})();
// const hiPSLevels= computeHipsLevels();
const IMAGE_ZOOM_MAX= levels[levels.length-1];
const HIPS_ZOOM_MAX= hiPSLevels[hiPSLevels.length-1];
/**
* can be 'UP','DOWN', 'FIT', 'FILL', 'ONE', 'LEVEL', 'WCS_MATCH_PREV'
* @public
* @global
*/
export const UserZoomTypes= new Enum(['UP','DOWN', 'FIT', 'FILL', 'ONE', 'LEVEL', 'WCS_MATCH_PREV'], { ignoreCase: true });
/**
*
* @param {WebPlot} plot
* @param {ZoomType} zoomType
* @return {number}
*/
export function getNextZoomLevel(plot, zoomType) {
const {zoomFactor}= plot;
const availableLevels= isImage(plot) ? levels : hiPSLevels;
const zoomMax= isImage(plot) ? IMAGE_ZOOM_MAX : HIPS_ZOOM_MAX;
let newLevel= 1;
if (zoomType===UserZoomTypes.UP) {
newLevel= zoomFactor>=zoomMax ? zoomMax : availableLevels.find( (l) => l>zoomFactor);
}
else if (zoomType===UserZoomTypes.ONE) {
newLevel= 1;
}
else if (zoomType===UserZoomTypes.DOWN) {
newLevel= availableLevels[0];
let found= false;
for(let i= availableLevels.length-1; (i>=0); i--) {
found= (availableLevels[i]<zoomFactor);
if (found) {
newLevel= availableLevels[i];
break;
}
}
}
else {
logError('unsupported zoomType');
}
return newLevel;
}
/**
*
* @param plot
* @param screenDim
* @param fullType
* @param tryMinFactor
*/
export function getEstimatedFullZoomFactor(plot, screenDim, fullType, tryMinFactor=-1) {
const {width,height} = screenDim;
let overrideFullType= fullType;
if (plot.attributes[PlotAttribute.EXPANDED_TO_FIT_TYPE]) {
const s= plot.attributes[PlotAttribute.EXPANDED_TO_FIT_TYPE];
if (VisUtil.FullType.has(s)) overrideFullType= VisUtil.FullType.get(s);
}
return VisUtil.getEstimatedFullZoomFactor(overrideFullType, plot.dataWidth, plot.dataHeight,
width,height, tryMinFactor);
}
export function getZoomMax(plot) { return isImage(plot) ? levels[levels.length-1] : hiPSLevels[hiPSLevels.length-1]; }
function getOnePlusLevelDesc(level) {
let retval;
const remainder= level % 1;
if (remainder < .1 || remainder>.9) {
retval= Math.round(level)+'x';
}
else {
retval= numeral(level).format('0.000')+'x';
}
return retval;
}
/**
* Get the scale in arcsec / pixel of a plot as the given zoom factor
* @param plot
* @param zoomFact
* @return {number}
*/
export function getArcSecPerPix(plot, zoomFact) {
return getPixScaleArcSec(plot) / zoomFact;
}
export function getZoomLevelForScale(plot, arcsecPerPix) {
return getPixScaleArcSec(plot) / arcsecPerPix;
}
export function convertZoomToString(level) {
let retval;
const zfInt= Math.floor(level*10000);
if (zfInt>=10000) retval= getOnePlusLevelDesc(level); // if level > then 1.0
else if (zfInt===39) retval= '1/256x'; // 1/256
else if (zfInt===78) retval= '1/128x'; // 1/128
else if (zfInt===156) retval= '1/64x'; // 1/64
else if (zfInt===312) retval= '1/32x'; // 1/32
else if (zfInt===625) retval= '1/16x'; // 1/16
else if (zfInt===1250) retval= '1/8x'; // 1/8
else if (zfInt===2500) retval= String.fromCharCode(188) +'x'; // 1/4
else if (zfInt===7500) retval= String.fromCharCode(190) +'x'; // 3/4
else if (zfInt===5000) retval= String.fromCharCode(189) +'x'; // 1/2
else if (level<.125) retval= numeral(level).format('0.000')+'x';
else retval= numeral(level).format('0.0')+'x';
return retval;
}
const formatFOV = (charCode, fNum) => {
const nFormat = (fNum > 10.0) ? '0' : ((fNum >= 1.0) ? '0.0' : '0.00');
return `${numeral(fNum).format(nFormat)}${charCode}`;
};
export function makeFoVString(fov) {
let fovFormatted;
if (isNaN(fov)) return '';
if (fov > 1.0) {
fovFormatted= formatFOV(String.fromCharCode(176), fov);
} else {
const fovMin = VisUtil.convertAngle('deg', 'arcmin', fov);
fovFormatted= fovMin > 1.0 ? formatFOV("'", fovMin) :
formatFOV('"', VisUtil.convertAngle('arcmin', 'arcsec', fovMin));
}
return fovFormatted;
}
/**
*
* @param {PlotView} pv
* @return {{fovFormatted:string,zoomLevelFormatted:string}}
*/
export function getZoomDesc(pv) {
const plot= primePlot(pv);
if (!plot || !plot.viewDim) return {fovFormatted:'',zoomLevelFormatted:''};
const zoomLevelFormatted= isImage(plot) ? convertZoomToString(plot.zoomFactor) : '';
const fovFormatted= makeFoVString(getFoV(pv));
return {fovFormatted,zoomLevelFormatted};
}