import {ShapesFactory} from "./olqv_shapes.js";
import {getLoading} from "./domelements.js"
/** A class to create and to manage rectangular boxes in the 2D part of YAFITS. A box is basically defined by a pair of opposite corners.
*
* Boxes are created and manipulated with the {@link https://openlayers.org/en/v5.3.0/apidoc/|OpenLayers} API. In particular the {@link https://openlayers.org/en/v5.3.0/apidoc/module-ol_interaction_DragBox.html|DragBox} and {@link https://openlayers.org/en/v5.3.0/apidoc/module-ol_Feature-Feature.html|Feature} classes are used.
*
* <ul>
* <li>Boxes have their side parallels to the image sides (No rotation possible).</li>
* <li>A method is provided to obtain measurements associated to the collection of pixels contained in a box. </li>
* </ul>
*
* @extends ShapesFactory
*/
class BoxesFactory extends ShapesFactory {
static enter(what) {
console.group(this.name + "." + what);
}
static exit() {
console.groupEnd();
}
/**
* Creates an instance.
* @param {Viewer} viewer instance of the Viewer class that will host the boxes.
*/
constructor(viewer) {
super(viewer, 'box');
BoxesFactory.enter(this.constructor.name);
this.mode = this;
this.lastSelectedBox = null;
this.layer.setZIndex(12);
this.button = document.createElement("button");
this.button.setAttribute("type", "button");
this.button.setAttribute("class", "btn btn-primary btn-sm");
this.button.setAttribute("data-tooltip", "tooltip");
this.button.setAttribute("title", "Work with boxes");
this.button.append("B");
let f = function (event) {if (this.isOpened) this.close(); else this.open(this.dragBox, 'nesw-resize'); };
this.button.onclick = f.bind(this);
this.numOfBoxes = 0; // The number of boxes created sbsiao far
/*
** This is our dragbox interaction
*/
this.dragBox = new ol.interaction.DragBox({ condition: ol.events.condition.platformModifierKeyOnly });
this.dragBox.on('boxend', () => {
ShapesFactory.enter("this.dragBox.on('boxend', function() { : entering");
var extent = this.dragBox.getGeometry().getExtent();
// The real work when a drag box interaction reach its end is done below ( saynchronously )
//this.createAndMeasureBox(this.relFITSFilePath, this.viewer.getSliceRange()[0], extent[0], extent[2], extent[1], extent[3]);
let box = this.prepareBox(extent[0], extent[2], extent[1], extent[3]);
this.measure(box);
this.numOfBoxes += 1;
ShapesFactory.exit();
});
/*
** This the behaviour when a box has been selected.
*/
this.selector.select['Polygon'] = (feature) => {
ShapesFactory.enter("A box is selected");
this.selected(feature);
ShapesFactory.exit();
};
/*
** This the behaviour when a box has been unselected.
*/
this.selector.unselect['Polygon'] = (feature) => {
ShapesFactory.enter("A box is unselected");
this.unselected(feature);
ShapesFactory.exit();
};
/*
** This is the behaviour when a selected box is going to be removed
*/
this.selector.remove['Polygon'] = (f) => {
ShapesFactory.enter("A selected box is about to be removed");
this.remove(f);
ShapesFactory.exit();
};
BoxesFactory.exit();
}
/**
* Utility. Returns the toolbox button that will activate this instance.
* @returns a {@link https://developer.mozilla.org/fr/docs/Web/HTML/Element/Button|button}
*/
getButton() {
return this.button;
}
/**
* Creates an OpenLayers feature that describres a box given bottom left and upper right coordinates.
* A label is automatically generated that will be displayed beside the box.
* @param {number} iRA0 lower 1st coordinate
* @param {*} iRA1 upper 1st coordinate
* @param {*} iDEC0 lower 2nd coordinate
* @param {*} iDEC1 upper 2nd coordinate
* @returns {Feature}
*/
prepareBox(iRA0, iRA1, iDEC0, iDEC1) {
ShapesFactory.enter(this.prepareBox.name);
getLoading().style.display = 'block';
var tl = [iRA0, iDEC1];
var tr = [iRA1, iDEC1];
var br = [iRA1, iDEC0];
var bl = [iRA0, iDEC0];
var corners = [];
corners.push(tl, tr, br, bl, tl);
let feature = new ol.Feature({ geometry: new ol.geom.Polygon([corners]) });
let properties = {};
properties["type"] = "box";
feature.set("properties", properties);
feature.set("label", `b_${this.numOfBoxes}`);
ShapesFactory.exit();
return feature;
}
/**
* Calculates some measurements associated to the box described in feature.
* The measurements are stored in an entry "measurements" of feature "properties" property.
*
* > The measurements are calculated remotely by the YAFITSS server.
*
* @param {Feature} feature the OpenLayers feature expected to represent a box.
* @param {boolean} addFeature Deprecated, don't use it.
*/
measure(feature, addFeature = true) {
BoxesFactory.enter(this.measure.name);
if (typeof this.viewer.getSliceRange() != "number") {
alert("Do not know how to measure a 2D box on an image representing a 3D dataset");
}
else {
let properties = feature.get("properties");
if (properties.hasOwnProperty("type") && properties["type"] === "box") {
getLoading().style.display = "block";
let corners = feature.getGeometry().getCoordinates()[0];
let iRA0, iRA1, iDEC0, iDEC1;
[iRA0, iRA1] = [Math.min(corners[0][0], corners[2][0]), Math.max(corners[0][0], corners[2][0])];
[iDEC0, iDEC1] = [Math.min(corners[0][1], corners[2][1]), Math.max(corners[0][1], corners[2][1])];
console.log(iRA0, iRA1, iDEC0, iDEC1);
$.post("measureBox", {
'relFITSFilePath': this.relFITSFilePath,
'iFREQ': this.viewer.getSliceRange(),
'iRA0': iRA0,
'iRA1': iRA1,
'iDEC0': iDEC0,
'iDEC1': iDEC1
},
(resp) => {
ShapesFactory.enter('measure callback: entering');
getLoading().style.display = "none";
if (resp["status"] == false) {
alert(`Something went wrong with the measurements of the box [[${iRA0}, ${iDEC0}], [${iRA1},${iDEC1}]]. The message was '${resp["message"]}'`);
}
else {
properties["measurements"] = resp["result"];
feature.set("properties", properties);
if (addFeature) {
feature.setStyle(this.style_f(feature));
this.source.addFeature(feature);
}
}
ShapesFactory.exit();
});
}
else {
console.log("Unable to measure such a feature");
}
}
BoxesFactory.exit();
}
/**
* Behaviour when an instance is activated.
*
* @see {@link https://openlayers.org/en/v5.3.0/apidoc/module-ol_interaction_Interaction-Interaction.html|Interaction }
* @see {@link https://developer.mozilla.org/fr/docs/Web/CSS/cursor | cursor}
* @param {Interaction} interaction
* @param {cursor} cursor
*/
open(interaction, cursor) {
BoxesFactory.enter(this.open.name);
super.open(interaction, cursor);
BoxesFactory.exit();
}
/**
* Behaviour when a box is selected.
* @param {Feature} box
*/
selected(box) {
ShapesFactory.enter(this.selected.name);
super.selected(box);
ShapesFactory.exit();
}
}
export {
BoxesFactory
}