mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-12 07:40:26 -08:00
Shape function given to a catalog
* fix: returning nothing or an invalid value from it will displays the source as the square shape. Before, it was forgetting to display the source * Possibility to return a string in "rhomb", "circle", "square", "cross", "triangle" from it. * Set the color of footprint to the color of the Catalog. This thus overwrites the color that could have been given in the footprint directly. To compensate that, I think it could be great to allow a color func as well.
This commit is contained in:
committed by
Matthieu Baumann
parent
ebb9d6d3d6
commit
6bd9c43d88
@@ -33,10 +33,6 @@ import { Coo } from "./libs/astro/coo.js";
|
|||||||
import { VOTable } from "./vo/VOTable.js";
|
import { VOTable } from "./vo/VOTable.js";
|
||||||
import { ObsCore } from "./vo/ObsCore.js";
|
import { ObsCore } from "./vo/ObsCore.js";
|
||||||
import A from "./A.js";
|
import A from "./A.js";
|
||||||
import { Polyline } from "./shapes/Polyline.js";
|
|
||||||
import { Vector } from "./shapes/Vector.js";
|
|
||||||
import { Ellipse } from "./shapes/Ellipse.js";
|
|
||||||
import { Circle } from "./shapes/Circle.js";
|
|
||||||
import { Footprint } from "./Footprint.js";
|
import { Footprint } from "./Footprint.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,6 +44,7 @@ import { Footprint } from "./Footprint.js";
|
|||||||
* @property {string} [color] - The color associated with the catalog.
|
* @property {string} [color] - The color associated with the catalog.
|
||||||
* @property {number} [sourceSize=8] - The size of the sources in the catalog.
|
* @property {number} [sourceSize=8] - The size of the sources in the catalog.
|
||||||
* @property {string|Function|Image|HTMLCanvasElement|HTMLImageElement} [shape="square"] - The shape of the sources (can be, "square", "circle", "plus", "cross", "rhomb", "triangle").
|
* @property {string|Function|Image|HTMLCanvasElement|HTMLImageElement} [shape="square"] - The shape of the sources (can be, "square", "circle", "plus", "cross", "rhomb", "triangle").
|
||||||
|
If a function is given, user can return Image, HTMLImageCanvas, HTMLImageElement or a string being in ["square", "circle", "plus", "cross", "rhomb", "triangle"]. This allows to define different shape for a specific catalog source.
|
||||||
* @property {number} [limit] - The maximum number of sources to display.
|
* @property {number} [limit] - The maximum number of sources to display.
|
||||||
* @property {string|Function} [onClick] - Whether the source data appears as a table row or a in popup. Can be 'showTable' string, 'showPopup' string or a custom user defined function that handles the click.
|
* @property {string|Function} [onClick] - Whether the source data appears as a table row or a in popup. Can be 'showTable' string, 'showPopup' string or a custom user defined function that handles the click.
|
||||||
* @property {boolean} [readOnly=false] - Whether the catalog is read-only.
|
* @property {boolean} [readOnly=false] - Whether the catalog is read-only.
|
||||||
@@ -60,7 +57,7 @@ import { Footprint } from "./Footprint.js";
|
|||||||
* @property {string} [labelColumn] - The name of the column to be used for the label.
|
* @property {string} [labelColumn] - The name of the column to be used for the label.
|
||||||
* @property {string} [labelColor=color] - The color of the source labels.
|
* @property {string} [labelColor=color] - The color of the source labels.
|
||||||
* @property {string} [labelFont="10px sans-serif"] - The font for the source labels.
|
* @property {string} [labelFont="10px sans-serif"] - The font for the source labels.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export let Catalog = (function () {
|
export let Catalog = (function () {
|
||||||
/**
|
/**
|
||||||
@@ -71,28 +68,21 @@ export let Catalog = (function () {
|
|||||||
* @param {CatalogOptions} options - Configuration options for the catalog.
|
* @param {CatalogOptions} options - Configuration options for the catalog.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const catalogOptions = {
|
* aladin.addCatalog(A.catalogFromVizieR("VII/237/pgc", "M31", 3, {
|
||||||
* url: "https://example.com/catalog",
|
|
||||||
* name: "My Catalog",
|
|
||||||
* color: "#ff0000",
|
|
||||||
* sourceSize: 10,
|
|
||||||
* markerSize: 15,
|
|
||||||
* shape: "circle",
|
|
||||||
* limit: 1000,
|
* limit: 1000,
|
||||||
* onClick: (source) => {
|
* onClick: 'showTable',
|
||||||
* // handle sources
|
* color: 'yellow',
|
||||||
* },
|
* hoverColor: 'blue',
|
||||||
* readOnly: true,
|
* shape: (s) => {
|
||||||
* raField: "ra",
|
* let coo = A.coo();
|
||||||
* decField: "dec",
|
* coo.parse(s.data['RAJ2000'] + ' ' + s.data['DEJ2000'])
|
||||||
* filter: (source) => source.mag < 15,
|
*
|
||||||
* selectionColor: "#00ff00",
|
* let a = (0.1 * Math.pow(10, +s.data.logD25)) / 60;
|
||||||
* hoverColor: "#ff00ff",
|
* let b = (1.0 / Math.pow(10, +s.data.logR25)) * a
|
||||||
* displayLabel: true,
|
*
|
||||||
* labelColor: "#00ff00",
|
* return A.ellipse(coo.lon, coo.lat, a, b, +s.data.PA, {lineWidth: 3});
|
||||||
* labelFont: "12px Arial"
|
* }
|
||||||
* };
|
* }));
|
||||||
* const myCatalog = new Catalog(catalogOptions);
|
|
||||||
*/
|
*/
|
||||||
function Catalog(options) {
|
function Catalog(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
@@ -158,6 +148,11 @@ export let Catalog = (function () {
|
|||||||
this.isShowing = true;
|
this.isShowing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Catalog.shapes = ['plus', 'cross', 'rhomb', 'triangle', 'circle', 'square'];
|
||||||
|
Catalog.cacheCanvas = {}
|
||||||
|
Catalog.cacheHoverCanvas = {}
|
||||||
|
Catalog.cacheSelectCanvas = {}
|
||||||
|
|
||||||
Catalog.createShape = function (shapeName, color, sourceSize) {
|
Catalog.createShape = function (shapeName, color, sourceSize) {
|
||||||
if (
|
if (
|
||||||
shapeName instanceof Image ||
|
shapeName instanceof Image ||
|
||||||
@@ -417,8 +412,6 @@ export let Catalog = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let sources = [];
|
let sources = [];
|
||||||
//let footprints = [];
|
|
||||||
|
|
||||||
var coo = new Coo();
|
var coo = new Coo();
|
||||||
|
|
||||||
rows.every((row) => {
|
rows.every((row) => {
|
||||||
@@ -506,9 +499,10 @@ export let Catalog = (function () {
|
|||||||
this.onClick = options.onClick || this.onClick;
|
this.onClick = options.onClick || this.onClick;
|
||||||
|
|
||||||
this._shapeIsFunction = false; // if true, the shape is a function drawing on the canvas
|
this._shapeIsFunction = false; // if true, the shape is a function drawing on the canvas
|
||||||
this._shapeIsFootprintFunction = false;
|
|
||||||
if (typeof this.shape === "function") {
|
if (typeof this.shape === "function") {
|
||||||
this._shapeIsFunction = true;
|
this._shapeIsFunction = true;
|
||||||
|
// A shape function that operates on the canvas gives the ctx and fov params
|
||||||
|
this._shapeOperatesOnCtx = this.shape.length > 1;
|
||||||
// do not need to compute any canvas
|
// do not need to compute any canvas
|
||||||
|
|
||||||
// there is a possibility that the user gives a function returning shape objects such as
|
// there is a possibility that the user gives a function returning shape objects such as
|
||||||
@@ -523,26 +517,36 @@ export let Catalog = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.selectSize = this.sourceSize + 2;
|
this.selectSize = this.sourceSize + 2;
|
||||||
|
// Create all the variant shaped canvas
|
||||||
|
this.cacheCanvas = {}
|
||||||
|
this.cacheHoverCanvas = {}
|
||||||
|
this.cacheSelectCanvas = {}
|
||||||
|
|
||||||
this.cacheCanvas = Catalog.createShape(
|
for (var shape of Catalog.shapes) {
|
||||||
this.shape,
|
this.cacheCanvas[shape] = Catalog.createShape(
|
||||||
this.color,
|
shape,
|
||||||
this.sourceSize
|
this.color,
|
||||||
);
|
this.sourceSize
|
||||||
this.cacheSelectCanvas = Catalog.createShape(
|
)
|
||||||
this.shape,
|
|
||||||
this.selectionColor,
|
this.cacheHoverCanvas[shape] = Catalog.createShape(
|
||||||
this.selectSize
|
shape,
|
||||||
);
|
this.hoverColor,
|
||||||
this.cacheHoverCanvas = Catalog.createShape(
|
this.selectSize
|
||||||
this.shape,
|
);
|
||||||
this.hoverColor,
|
|
||||||
this.selectSize
|
this.cacheSelectCanvas[shape] = Catalog.createShape(
|
||||||
);
|
shape,
|
||||||
|
this.selectionColor,
|
||||||
|
this.selectSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this.reportChange();
|
this.reportChange();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add sources to the catalog
|
* Add sources to the catalog
|
||||||
*
|
*
|
||||||
@@ -587,18 +591,32 @@ export let Catalog = (function () {
|
|||||||
Catalog.prototype.computeFootprints = function (sources) {
|
Catalog.prototype.computeFootprints = function (sources) {
|
||||||
let footprints = [];
|
let footprints = [];
|
||||||
|
|
||||||
if (this._shapeIsFunction) {
|
if (this._shapeIsFunction && !this._shapeOperatesOnCtx) {
|
||||||
for (const source of sources) {
|
for (let source of sources) {
|
||||||
try {
|
try {
|
||||||
let shapes = this.shape(source);
|
let shapes = this.shape(source);
|
||||||
if (shapes) {
|
if (shapes) {
|
||||||
shapes = [].concat(shapes);
|
shapes = [].concat(shapes);
|
||||||
|
|
||||||
// 1. return of the shape func is an image
|
// Result of the func is an image/canvas
|
||||||
if (shapes.length == 1 && (shapes[0] instanceof Image || shapes[0] instanceof HTMLCanvasElement)) {
|
if (shapes.length == 1 && (shapes[0] instanceof Image || shapes[0] instanceof HTMLCanvasElement)) {
|
||||||
source.setImage(shapes[0]);
|
source.setImage(shapes[0]);
|
||||||
// 2. return of the shape is a set of shapes or a footprint
|
// Result of the func is shape label ('cross', 'plus', ...)
|
||||||
|
} else if (shapes.length == 1 && typeof shapes[0] === "string") {
|
||||||
|
// If not found, select the square canvas
|
||||||
|
let shape = shapes[0] || "square";
|
||||||
|
source.setShape(shape)
|
||||||
|
// Result of the shape is a set of shapes or a footprint
|
||||||
} else {
|
} else {
|
||||||
|
for (var shape of shapes) {
|
||||||
|
// Set the same color of the shape than the catalog.
|
||||||
|
// FIXME: the color/shape could be a parameter at the source level, allowing the user single catalogs handling different shapes
|
||||||
|
shape.setColor(this.color)
|
||||||
|
|
||||||
|
shape.setSelectionColor(this.selectionColor);
|
||||||
|
shape.setHoverColor(this.hoverColor);
|
||||||
|
}
|
||||||
|
|
||||||
let footprint;
|
let footprint;
|
||||||
if (shapes.length == 1 && shapes[0] instanceof Footprint) {
|
if (shapes.length == 1 && shapes[0] instanceof Footprint) {
|
||||||
footprint = shapes[0];
|
footprint = shapes[0];
|
||||||
@@ -606,7 +624,6 @@ export let Catalog = (function () {
|
|||||||
footprint = new Footprint(shapes, source);
|
footprint = new Footprint(shapes, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._shapeIsFootprintFunction = true;
|
|
||||||
footprint.setCatalog(this);
|
footprint.setCatalog(this);
|
||||||
|
|
||||||
// store the footprints
|
// store the footprints
|
||||||
@@ -879,6 +896,7 @@ export let Catalog = (function () {
|
|||||||
ctx.save();
|
ctx.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const drawnSources = this.drawSources(ctx, width, height);
|
const drawnSources = this.drawSources(ctx, width, height);
|
||||||
|
|
||||||
if (this._shapeIsFunction) {
|
if (this._shapeIsFunction) {
|
||||||
@@ -942,7 +960,7 @@ export let Catalog = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (s.x <= width && s.x >= 0 && s.y <= height && s.y >= 0) {
|
if (s.x <= width && s.x >= 0 && s.y <= height && s.y >= 0) {
|
||||||
if (this._shapeIsFunction && !this._shapeIsFootprintFunction) {
|
if (this._shapeOperatesOnCtx) {
|
||||||
this.shape(s, ctx, this.view.getViewParams());
|
this.shape(s, ctx, this.view.getViewParams());
|
||||||
} else if (s.image) {
|
} else if (s.image) {
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
@@ -957,22 +975,27 @@ export let Catalog = (function () {
|
|||||||
s.y - this.sourceSize / 2
|
s.y - this.sourceSize / 2
|
||||||
);
|
);
|
||||||
} else if (s.isSelected) {
|
} else if (s.isSelected) {
|
||||||
|
let cacheSelectCanvas = this.cacheSelectCanvas[s.shape || this.shape] || this.cacheSelectCanvas["square"];
|
||||||
|
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
this.cacheSelectCanvas,
|
cacheSelectCanvas,
|
||||||
s.x - this.selectSize / 2,
|
s.x - this.selectSize / 2,
|
||||||
s.y - this.selectSize / 2
|
s.y - this.selectSize / 2
|
||||||
);
|
);
|
||||||
} else if (s.isHovered) {
|
} else if (s.isHovered) {
|
||||||
|
let cacheHoverCanvas = this.cacheHoverCanvas[s.shape || this.shape] || this.cacheHoverCanvas["square"];
|
||||||
|
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
this.cacheHoverCanvas,
|
cacheHoverCanvas,
|
||||||
s.x - this.selectSize / 2,
|
s.x - this.selectSize / 2,
|
||||||
s.y - this.selectSize / 2
|
s.y - this.selectSize / 2
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
let cacheCanvas = this.cacheCanvas[s.shape || this.shape] || this.cacheCanvas["square"];
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
this.cacheCanvas,
|
cacheCanvas,
|
||||||
s.x - this.cacheCanvas.width / 2,
|
s.x - cacheCanvas.width / 2,
|
||||||
s.y - this.cacheCanvas.height / 2
|
s.y - cacheCanvas.height / 2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,10 @@ export let Source = (function() {
|
|||||||
this.image = image;
|
this.image = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Source.prototype.setShape = function(shape) {
|
||||||
|
this.shape = shape;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulates a click on the source
|
* Simulates a click on the source
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1584,14 +1584,14 @@ export let View = (function () {
|
|||||||
|
|
||||||
View.prototype.increaseZoom = function () {
|
View.prototype.increaseZoom = function () {
|
||||||
this.zoom.apply({
|
this.zoom.apply({
|
||||||
stop: this.fov / 1.4,
|
stop: this.fov / 1.8,
|
||||||
duration: 100
|
duration: 100
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
View.prototype.decreaseZoom = function () {
|
View.prototype.decreaseZoom = function () {
|
||||||
this.zoom.apply({
|
this.zoom.apply({
|
||||||
stop: this.fov * 1.4,
|
stop: this.fov * 1.8,
|
||||||
duration: 100
|
duration: 100
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,31 +73,6 @@ export let Polyline = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*function _isAcrossCollignonZoneForHpxProjection(line, view) {
|
|
||||||
const [x1, y1] = view.wasm.screenToClip(line.x1, line.y1);
|
|
||||||
const [x2, y2] = view.wasm.screenToClip(line.x2, line.y2);
|
|
||||||
|
|
||||||
// x, y, between -1 and 1
|
|
||||||
let triIdxCollignionZone = function(x, y) {
|
|
||||||
let xZone = Math.floor((x * 0.5 + 0.5) * 4.0);
|
|
||||||
return xZone + 4 * (y > 0.0);
|
|
||||||
};
|
|
||||||
|
|
||||||
let isInCollignionZone = function(x, y) {
|
|
||||||
return Math.abs(y) > 0.5;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isInCollignionZone(x1, y1) && isInCollignionZone(x2, y2)) {
|
|
||||||
if (triIdxCollignionZone(x1, y1) === triIdxCollignionZone(x2, y2)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a polyline shape
|
* Represents a polyline shape
|
||||||
*
|
*
|
||||||
@@ -237,7 +212,6 @@ export let Polyline = (function() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(color)
|
|
||||||
this.hoverColor = color;
|
this.hoverColor = color;
|
||||||
if (this.overlay) {
|
if (this.overlay) {
|
||||||
this.overlay.reportChange();
|
this.overlay.reportChange();
|
||||||
|
|||||||
Reference in New Issue
Block a user