Compare commits

..

15 Commits

Author SHA1 Message Date
Matthieu Baumann
211e3797f5 final commit 2025-09-04 13:58:06 +02:00
Matthieu Baumann
e6d57a137e show sources of obscore table 2025-09-04 12:02:42 +02:00
Matthieu Baumann
c8604b6372 new onlyFootprint catalog option. If set to false, pointed sources are also shown with the footprint 2025-09-04 11:40:45 +02:00
Matthieu Baumann
91e1d70489 ellipse intersectBBox very coarse approx 2025-09-04 11:04:05 +02:00
Matthieu Baumann
301e004afc refac: compose Footprint inside Source and not the opposite 2025-09-03 17:58:54 +02:00
Matthieu Baumann
d4cf2d6523 wip commit 2025-09-02 17:08:17 +02:00
Matthieu Baumann
1b10c59dca Allow customizing size and color source from its data content
sourceSize and color properties when creating a new Catalog now accepts a function
allowing to set different sizes/colors in function of the source catalog row
2025-09-02 15:06:08 +02:00
Matthieu Baumann
f9b23d286c fine tune the default linewidth values 2025-08-29 16:07:11 +02:00
Matthieu Baumann
809a53e694 run clippy and fmt 2025-08-29 16:07:11 +02:00
Matthieu Baumann
d6583e47ef update default thickness to match with previous lineWidth user were interested of 2025-08-29 16:07:11 +02:00
bmatthieu3
0c9c315f69 anti aliasing on lines (grid + mocs) drawn by the gpu. Change moc linewidth from 3 -> 2 and twick the coogrid ang step/opacity/linewidth 2025-08-29 16:07:11 +02:00
Matthieu Baumann
3454083449 fix Circle::intersectBbox 2025-08-29 11:57:15 +02:00
Erik Mellegard
311fa84919 Fix Circle intersectBBox 2025-08-29 11:57:15 +02:00
Matthieu Baumann
3d445e4f6f fix 26 channel color offset 2025-08-28 17:52:45 +02:00
Matthieu Baumann
950d0c693e Fix wrong coordinates frame 2025-08-28 16:17:30 +02:00
23 changed files with 463 additions and 339 deletions

View File

@@ -26,8 +26,17 @@
limit: 1000,
//orderBy: 'nb_ref',
onClick: 'showTable',
color: 'yellow',
hoverColor: 'blue',
onlyFootprints: false,
color: (s) => {
let coo = A.coo();
coo.parse(s.data['RAJ2000'] + ' ' + s.data['DEJ2000'])
let a = (0.1 * Math.pow(10, +s.data.logD25)) / 60;
let b = (1.0 / Math.pow(10, +s.data.logR25)) * a
return `rgb(${s.data["logR25"]*255.0}, ${s.data["logR25"]*255.0}, 255)`
},
hoverColor: 'red',
shape: (s) => {
let coo = A.coo();
coo.parse(s.data['RAJ2000'] + ' ' + s.data['DEJ2000'])

View File

@@ -31,15 +31,21 @@
hoverColor: 'yellow',
selectionColor: 'white',
// Footprint associated to sources
shape: (s) => {
color: (s) => {
// discard drawing a vector for big pm
let totalPmSquared = s.data.pmra*s.data.pmra + s.data.pmdec*s.data.pmdec;
if (totalPmSquared > 6) {
return;
}
let color = rainbowColorMap((totalPmSquared - 2.5) / 2)
return rainbowColorMap((totalPmSquared - 2.5) / 2)
},
shape: (s) => {
// discard drawing a vector for big pm
let totalPmSquared = s.data.pmra*s.data.pmra + s.data.pmdec*s.data.pmdec;
if (totalPmSquared > 6) {
return;
}
// Compute the mean of pm over the catalog sources
if (!pmraMean || !pmdecMean) {
pmraMean = 0, pmdecMean = 0;
@@ -62,13 +68,24 @@
s.dec,
s.ra + dra,
s.dec + ddec,
{color}
)
}
},
() => {
aladin.addCatalog(pmCat);
pmCat.select((s) => {
let totalPmSquared = s.data.pmra*s.data.pmra + s.data.pmdec*s.data.pmdec;
if (totalPmSquared > 6) {
return false;
}
return totalPmSquared < 3.0;
});
});
aladin.addCatalog(pmCat);
});
function rainbowColorMap(value) {
// Ensure value is within range [0, 1]
value = Math.max(0, Math.min(1, value));

View File

@@ -133,7 +133,6 @@ impl App {
//let exec = Rc::new(RefCell::new(TaskExecutor::new()));
let projection = ProjectionType::Sin(mapproj::zenithal::sin::Sin);
gl.enable(WebGl2RenderingContext::BLEND);
// TODO: https://caniuse.com/?search=scissor is not supported for safari <= 14.1
// When it will be supported nearly everywhere, we will need to uncomment this line to
@@ -829,6 +828,7 @@ impl App {
// Render the scene
// Clear all the screen first (only the region set by the scissor)
gl.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT);
// set the blending options
layers.draw(camera, shaders, colormaps, projection)?;
@@ -844,12 +844,12 @@ impl App {
);*/
moc.draw(camera, projection, shaders)?;
gl.blend_func_separate(
/*gl.blend_func_separate(
WebGl2RenderingContext::SRC_ALPHA,
WebGl2RenderingContext::ONE,
WebGl2RenderingContext::ONE,
WebGl2RenderingContext::ONE,
);
);*/
grid.draw(camera, projection, shaders)?;
// Ok(())
// },

View File

@@ -198,14 +198,15 @@ impl ProjetedGrid {
if self.enabled {
let fov = camera.get_field_of_view();
let bbox = fov.get_bounding_box();
let max_dim_px = camera.get_width().max(camera.get_height()) as f64;
let step_line_px = max_dim_px * 0.2;
//let max_dim_px = camera.get_width().max(camera.get_height()) as f64;
//let step_line_px = max_dim_px * 0.15;
let aspect = camera.get_aspect() as f64;
// update meridians
self.meridians = {
// Select the good step with a binary search
let step_lon_precised =
bbox.get_lon_size() * step_line_px / (camera.get_width() as f64);
let step_lon_precised = bbox.get_lon_size() * 0.15;
let step_lon = select_fixed_step(step_lon_precised);
let decimal_lon_prec = step_lon.to_degrees().log10().abs().ceil() as u8;
@@ -235,8 +236,7 @@ impl ProjetedGrid {
};
self.parallels = {
let step_lat_precised =
bbox.get_lat_size() * step_line_px / (camera.get_height() as f64);
let step_lat_precised = aspect * bbox.get_lat_size() * 0.15;
let step_lat = select_fixed_step(step_lat_precised);
let decimal_lat_prec = step_lat.to_degrees().log10().abs().ceil() as u8;
@@ -349,7 +349,7 @@ const GRID_STEPS: &[f64] = &[
0.08726647,
0.17453293,
0.34906585,
std::f64::consts::FRAC_PI_4,
std::f64::consts::FRAC_PI_6,
];
fn select_fixed_step(fov: f64) -> f64 {

View File

@@ -213,9 +213,13 @@ impl Layers {
let raytracer = &self.raytracer;
let raytracing = camera.is_raytracing(projection);
// The first layer or the background must be plot with no blending
self.gl.disable(WebGl2RenderingContext::BLEND);
// Check whether a hips to plot is allsky
// if neither are, we draw a font
// if there are, we do not draw nothing
let mut idx_start_layer = -1;
for (idx, layer) in self.layers.iter().enumerate() {
@@ -235,6 +239,8 @@ impl Layers {
}
}
let mut blending_enabled = false;
// Need to render transparency font
if idx_start_layer == -1 {
let vao = if raytracing {
@@ -258,6 +264,9 @@ impl Layers {
// The background (index -1) has been drawn, we can draw the first HiPS
idx_start_layer = 0;
self.gl.enable(WebGl2RenderingContext::BLEND);
blending_enabled = true;
}
let layers_to_render = &self.layers[(idx_start_layer as usize)..];
@@ -283,6 +292,11 @@ impl Layers {
}
}
}
if !blending_enabled {
self.gl.enable(WebGl2RenderingContext::BLEND);
blending_enabled = true;
}
}
Ok(())

View File

@@ -1,17 +1,25 @@
#version 300 es
precision lowp float;
precision highp float;
out vec4 color;
in float l;
in vec2 l;
uniform vec4 u_color;
uniform float u_thickness;
uniform float u_width;
uniform float u_height;
void main() {
// Multiply vertex color with texture color (in linear space).
// Linear color is written and blended in Framebuffer and converted to sRGB later
if (l > 0.05) {
if (l.x > 0.05) {
discard;
} else {
color = u_color;
// distance from line to compute the anti-aliasing
float dist = abs((u_thickness + 2.0) * l.y);
float half_thickness = (u_thickness + 2.0) * 0.5;
color.a = color.a * (1.0 - smoothstep(half_thickness - 1.0, half_thickness, dist));
}
}

View File

@@ -11,7 +11,7 @@ uniform float u_width;
uniform float u_height;
uniform float u_thickness;
out float l;
out vec2 l;
#include ../projection/projection.glsl;
@@ -27,7 +27,6 @@ void main() {
vec2 p_b_clip = proj(p_b_w);
vec2 da = p_a_clip - p_b_clip;
l = dot(da, da);
vec2 p_a_ndc = p_a_clip / (ndc_to_clip * czf);
vec2 p_b_ndc = p_b_clip / (ndc_to_clip * czf);
@@ -37,6 +36,12 @@ void main() {
vec2 y_b = normalize(vec2(-x_b.y, x_b.x));
float ndc2pix = 2.0 / u_width;
vec2 p_ndc = p_a_ndc + x_b * vertex.x + u_thickness * y_b * vertex.y * vec2(1.0, u_width/u_height) * ndc2pix;
vec2 p_ndc_x = x_b * vertex.x;
vec2 p_ndc_y = (u_thickness + 2.0) * y_b * vertex.y * vec2(1.0, u_width/u_height) * ndc2pix;
vec2 p_ndc = p_a_ndc + p_ndc_x + p_ndc_y;
gl_Position = vec4(p_ndc, 0.f, 1.f);
l = vec2(dot(da, da), vertex.y);
}

View File

@@ -4,7 +4,7 @@ layout (location = 0) in vec2 p_a;
layout (location = 1) in vec2 p_b;
layout (location = 2) in vec2 vertex;
out float l;
out vec2 l;
uniform float u_width;
uniform float u_height;
@@ -16,6 +16,7 @@ void main() {
float ndc2pix = 2.0 / u_width;
vec2 p = p_a + x_b * vertex.x + u_thickness * y_b * vertex.y * vec2(1.0, u_width/u_height) * ndc2pix;
vec2 p = p_a + x_b * vertex.x + (u_thickness + 2.0) * y_b * vertex.y * vec2(1.0, u_width/u_height) * ndc2pix;
gl_Position = vec4(p, 0.f, 1.f);
l = vec2(0.0, vertex.y);
}

View File

@@ -573,6 +573,10 @@ A.catalogFromURL = function (url, options, successCallback, errorCallback, usePr
const processVOTable = function (table) {
let {sources, fields} = table;
c.setFields(fields);
if (fields.s_region) {
// for ObsCore tables, show also the (ra, dec) as a source
c.onlyFootprints = false;
}
c.addSources(sources);
const s_regionFieldFound = Array.from(Object.keys(fields)).find((f) => f.toLowerCase() === 's_region');

View File

@@ -736,7 +736,7 @@ export let Aladin = (function () {
gridOptions: {
enabled: false,
showLabels: true,
thickness: 2,
thickness: 1,
labelSize: 15,
},
projection: "SIN",

View File

@@ -36,13 +36,13 @@ import A from "./A.js";
import { Footprint } from "./Footprint.js";
/**
* Represents options for configuring a catalog.
*
* @typedef {Object} CatalogOptions
* Represents options for configuring a catalog.
*
* @typedef {Object} CatalogOptions
* @property {string} url - The URL of the catalog.
* @property {string} [name="catalog"] - The name of the catalog.
* @property {string} [color] - The color associated with the catalog.
* @property {number} [sourceSize=8] - The size of the sources in the catalog.
* @property {string|Function} [color] - The color associated with the catalog. A function can be given similar to `shape`.
* @property {number|Function} [sourceSize=8] - The size of the sources in the catalog. A function can be given similar to `shape`.
* @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.
@@ -57,6 +57,7 @@ If a function is given, user can return Image, HTMLImageCanvas, HTMLImageElement
* @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} [labelFont="10px sans-serif"] - The font for the source labels.
* @property {boolean} [onlyFootprints=true] - When shapes/footprints are associated to a source (through a shape function given), decide wheter to show the point source as well. Point source is hidden by default
*/
export let Catalog = (function () {
@@ -95,6 +96,10 @@ export let Catalog = (function () {
this.markerSize = options.sourceSize || 12;
this.selectSize = this.sourceSize;
this.shape = options.shape || "square";
if (typeof this.shape === "function") {
this.shapeFn = this.shape;
this.shape = "custom";
}
this.maxNbSources = options.limit || undefined;
this.onClick = options.onClick || undefined;
this.readOnly = options.readOnly || false;
@@ -105,10 +110,14 @@ export let Catalog = (function () {
// allows for filtering of sources
this.filterFn = options.filter || undefined; // TODO: do the same for catalog
this.selectionColor = options.selectionColor || "#00ff00";
this.hoverColor = options.hoverColor || this.color;
this.hoverColor = options.hoverColor || undefined;
// when footprints are associated to source, do we need to draw the point source as well ?
this.onlyFootprints = options.onlyFootprints ?? true;
this.displayLabel = options.displayLabel || false;
this.labelColor = options.labelColor || this.color;
this.labelColor = options.labelColor || undefined;
this.labelFont = options.labelFont || "10px sans-serif";
if (this.displayLabel) {
this.labelColumn = options.labelColumn;
@@ -126,7 +135,6 @@ export let Catalog = (function () {
this.sources = [];
this.ra = [];
this.dec = [];
this.footprints = [];
// create this.cacheCanvas
// cacheCanvas permet de ne créer le path de la source qu'une fois, et de le réutiliser (cf. http://simonsarris.com/blog/427-increasing-performance-by-caching-paths-on-canvas)
@@ -463,7 +471,6 @@ export let Catalog = (function () {
if (successCallback) {
successCallback({
sources,
//footprints,
fields,
});
}
@@ -475,6 +482,18 @@ export let Catalog = (function () {
);
};
Catalog.prototype.getCacheCanvas = function(shape, color, size) {
const key = `${shape}_${size}_${color}`;
if (!(key in this.cacheCanvas)) {
this.cacheCanvas[key] = Catalog.createShape(
shape,
color,
size
)
}
return this.cacheCanvas[key];
};
/**
* Set the shape of the sources
*
@@ -493,16 +512,18 @@ export let Catalog = (function () {
options = options || {};
this.color = options.color || this.color || Color.getNextColor();
this.selectionColor = options.selectionColor || this.selectionColor || Color.getNextColor();
this.hoverColor = options.hoverColor || this.hoverColor || this.color;
this.hoverColor = options.hoverColor || this.hoverColor || undefined;
this.sourceSize = options.sourceSize || this.sourceSize || 6;
this.shape = options.shape || this.shape || "square";
if (typeof this.shape === "function") {
this.shapeFn = this.shape;
this.shape = "custom"
}
this.onClick = options.onClick || this.onClick;
this._shapeIsFunction = false; // if true, the shape is a function drawing on the canvas
if (typeof this.shape === "function") {
this._shapeIsFunction = true;
if (this.shapeFn) {
// A shape function that operates on the canvas gives the ctx and fov params
this._shapeOperatesOnCtx = this.shape.length > 1;
this._shapeOperatesOnCtx = this.shapeFn.length > 1;
// do not need to compute any canvas
// there is a possibility that the user gives a function returning shape objects such as
@@ -517,31 +538,21 @@ export let Catalog = (function () {
this._shapeIsImageOrCanvas = true;
}
this.selectSize = this.sourceSize + 2;
if (typeof this.color === "function") {
this.colorFn = this.color;
this.color = "custom"
}
if (typeof this.sourceSize === "function") {
this.sourceSizeFn = this.sourceSize;
this.sourceSize = "custom";
} else {
this.selectSize = this.sourceSize + 2;
}
// Create all the variant shaped canvas
this.cacheCanvas = {}
this.cacheHoverCanvas = {}
this.cacheSelectCanvas = {}
for (var shape of Catalog.shapes) {
this.cacheCanvas[shape] = Catalog.createShape(
shape,
this.color,
this.sourceSize
)
this.cacheHoverCanvas[shape] = Catalog.createShape(
shape,
this.hoverColor,
this.selectSize
);
this.cacheSelectCanvas[shape] = Catalog.createShape(
shape,
this.selectionColor,
this.selectSize
);
}
this.computeFootprints(this.sources);
this.reportChange();
};
@@ -584,61 +595,85 @@ export let Catalog = (function () {
this.dec.push(sources[k].dec);
}
this.recomputeFootprints = true;
this.computeFootprints(this.sources);
this.reportChange();
};
Catalog.prototype.computeFootprints = function (sources) {
let footprints = [];
if (this._shapeIsFunction && !this._shapeOperatesOnCtx) {
if ((this.shapeFn || this.colorFn || this.sourceSizeFn) && !this._shapeOperatesOnCtx) {
for (let source of sources) {
try {
let shapes = this.shape(source);
if (shapes) {
shapes = [].concat(shapes);
if (this.shapeFn) {
try {
let shapes = this.shapeFn(source);
if (shapes) {
shapes = [].concat(shapes);
// Result of the func is an image/canvas
if (shapes.length == 1 && (shapes[0] instanceof Image || shapes[0] instanceof HTMLCanvasElement)) {
source.setImage(shapes[0]);
// 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 {
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;
if (shapes.length == 1 && shapes[0] instanceof Footprint) {
footprint = shapes[0];
// Result of the func is an image/canvas
if (shapes.length == 1 && (shapes[0] instanceof Image || shapes[0] instanceof HTMLCanvasElement)) {
source.setImage(shapes[0]);
// 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 {
footprint = new Footprint(shapes, source);
let color = (this.colorFn && this.colorFn(source)) || this.color;
let hoverColor = this.hoverColor || color;
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(color)
shape.setSelectionColor(this.selectionColor);
shape.setHoverColor(hoverColor);
}
let footprint;
if (shapes.length == 1 && shapes[0] instanceof Footprint) {
footprint = shapes[0];
} else {
footprint = new Footprint(shapes);
}
source.setFootprint(footprint)
}
footprint.setCatalog(this);
// store the footprints
footprints.push(footprint);
}
} catch (e) {
// do not create the footprint
console.warn("Shape computation error");
continue;
}
}
if (this.colorFn) {
try {
let color = this.colorFn(source);
if (color) {
source.setColor(color);
}
} catch (e) {
// do not create the footprint
console.warn("Source color computation error");
continue;
}
}
if (this.sourceSizeFn) {
try {
let size = this.sourceSizeFn(source);
if (size) {
source.setSize(size);
}
} catch (e) {
// do not create the footprint
console.warn("Source size computation error");
continue;
}
} catch (e) {
// do not create the footprint
console.warn("Return of shape function could not be interpreted as a footprint");
continue;
}
}
}
return footprints;
};
Catalog.prototype.setFields = function (fields) {
@@ -710,17 +745,6 @@ export let Catalog = (function () {
return this.sources;
};
/**
* Get all the footprints
*
* @memberof Catalog
*
* @returns {Footprint[]} - an array of all the footprints in the catalog object
*/
Catalog.prototype.getFootprints = function () {
return this.footprints;
};
/**
* Select all the source catalog
*
@@ -801,6 +825,32 @@ export let Catalog = (function () {
this.updateShape();
};
/**
* Select sources of the catalog matching a given callback
*
* @memberof Catalog
*
* @param {Function} filter - A filter callback to select sources of a catalog.
*/
Catalog.prototype.select = function(filter) {
let selection = [];
if (typeof filter === "function") {
for ( var s of this.sources ) {
if (filter(s)) {
selection.push(s)
}
}
this.view.selectObjects([selection]);
}
if (this.view && this.view.aladin.callbacksByEventName) {
var callback = this.view.aladin.callbacksByEventName['objectsSelected'] || this.view.aladin.callbacksByEventName['select'];
if (callback) {
callback([selection]);
}
}
}
/**
* Set the color of hovered sources
*
@@ -869,7 +919,7 @@ export let Catalog = (function () {
this.ra.splice(idx, 1);
this.dec.splice(idx, 1);
this.recomputeFootprints = true;
this.computeFootprints(this.sources);
this.reportChange();
};
@@ -884,7 +934,6 @@ export let Catalog = (function () {
this.sources = [];
this.ra = [];
this.dec = [];
this.footprints = [];
this.reportChange();
};
@@ -897,24 +946,21 @@ export let Catalog = (function () {
// tracé simple
ctx.strokeStyle = this.color;
// Draw the footprints first
this.drawFootprints(ctx);
if (this._shapeIsFunction) {
if (this.shapeFn) {
ctx.save();
}
const drawnSources = this.drawSources(ctx, width, height);
if (this._shapeIsFunction) {
if (this.shapeFn) {
ctx.restore();
}
// Draw labels
if (this.displayLabel) {
ctx.fillStyle = this.labelColor;
ctx.font = this.labelFont;
drawnSources.forEach((s) => {
ctx.fillStyle = this.labelColor || s.color || this.color;
this.drawSourceLabel(s, ctx);
});
}
@@ -922,6 +968,7 @@ export let Catalog = (function () {
Catalog.prototype.drawSources = function (ctx, width, height) {
let inside = [];
let self = this;
if (!this.sources) {
return;
@@ -936,8 +983,7 @@ export let Catalog = (function () {
return self.drawSource(s, ctx, width, height)
};
let self = this;
this.sources.forEach(function (s, idx) {
this.sources.forEach((s, idx) => {
let drawn = false;
if (xy[2 * idx] && xy[2 * idx + 1]) {
@@ -982,13 +1028,18 @@ export let Catalog = (function () {
return false;
}
if (s.hasFootprint && !s.tooSmallFootprint) {
return false;
if (s.isFootprint()) {
s.footprint.draw(ctx, this.view)
s.tooSmallFootprint = s.footprint.isTooSmall();
if (!s.tooSmallFootprint && this.onlyFootprints) {
return true;
}
}
if (s.x <= width && s.x >= 0 && s.y <= height && s.y >= 0) {
if (this._shapeOperatesOnCtx) {
this.shape(s, ctx, this.view.getViewParams());
this.shapeFn(s, ctx, this.view.getViewParams());
} else if (this._shapeIsImageOrCanvas) {
// Global catalog shape set as an Image, an HTMLCanvasElement or HTMLImageElement
let canvas = this.shape;
@@ -1011,23 +1062,34 @@ export let Catalog = (function () {
s.y - this.sourceSize / 2
);
} else if (s.isSelected) {
let cacheSelectCanvas = this.cacheSelectCanvas[s.shape || this.shape] || this.cacheSelectCanvas["square"];
let selectSize = (s.size || this.sourceSize) + 2;
let shape = s.shape || this.shape || "square"
let color = this.selectionColor;
let cacheSelectedCanvas = this.getCacheCanvas(shape, color, selectSize)
ctx.drawImage(
cacheSelectCanvas,
s.x - this.selectSize / 2,
s.y - this.selectSize / 2
cacheSelectedCanvas,
s.x - cacheSelectedCanvas.width / 2,
s.y - cacheSelectedCanvas.height / 2
);
} else if (s.isHovered) {
let cacheHoverCanvas = this.cacheHoverCanvas[s.shape || this.shape] || this.cacheHoverCanvas["square"];
let selectSize = (s.size || this.sourceSize) + 2;
let shape = s.shape || this.shape || "square"
let color = this.hoverColor || s.color || this.color;
let cacheHoverCanvas = this.getCacheCanvas(shape, color, selectSize)
ctx.drawImage(
cacheHoverCanvas,
s.x - this.selectSize / 2,
s.y - this.selectSize / 2
s.x - cacheHoverCanvas.width / 2,
s.y - cacheHoverCanvas.height / 2
);
} else {
let cacheCanvas = this.cacheCanvas[s.shape || this.shape] || this.cacheCanvas["square"];
let shape = s.shape || this.shape || "square"
let size = s.size || this.sourceSize;
let color = s.color || this.color;
let cacheCanvas = this.getCacheCanvas(shape, color, size)
ctx.drawImage(
cacheCanvas,
s.x - cacheCanvas.width / 2,
@@ -1054,32 +1116,6 @@ export let Catalog = (function () {
ctx.fillText(label, s.x, s.y);
};
Catalog.prototype.drawFootprints = function (ctx) {
if (this.recomputeFootprints) {
this.footprints = this.computeFootprints(this.sources);
this.recomputeFootprints = false;
}
var f;
for (let k = 0; k < this.footprints.length; k++) {
f = this.footprints[k];
if (this.filterFn && f.source) {
if(!this.filterFn(f.source)) {
f.hide()
} else {
f.show()
f.draw(ctx, this.view);
f.source.tooSmallFootprint = f.isTooSmall();
}
} else {
f.draw(ctx, this.view);
f.source.tooSmallFootprint = f.isTooSmall();
}
}
};
// callback function to be called when the status of one of the sources has changed
Catalog.prototype.reportChange = function () {
this.view && this.view.requestRedraw();
@@ -1095,10 +1131,6 @@ export let Catalog = (function () {
return;
}
this.isShowing = true;
// Dispatch to the footprints
if (this.footprints) {
this.footprints.forEach((f) => f.show());
}
this.reportChange();
};
@@ -1121,10 +1153,6 @@ export let Catalog = (function () {
) {
this.view.popup.hide();
}
// Dispatch to the footprints
if (this.footprints) {
this.footprints.forEach((f) => f.hide());
}
this.reportChange();
};

View File

@@ -45,7 +45,6 @@ export let DefaultActionsForContextMenu = (function () {
const a = aladinInstance;
const selectObjects = (selection) => {
console.log(selection)
a.view.selectObjects(selection);
};
return [

View File

@@ -37,14 +37,15 @@ import { Utils } from './Utils';
export let Footprint= (function() {
// constructor
let Footprint = function(shapes, source) {
//let Footprint = function(shapes, source) {
let Footprint = function(shapes) {
// All graphics overlay have an id
this.id = 'footprint-' + Utils.uuidv4();
this.source = source;
/*this.source = source;
if (this.source) {
this.source.hasFootprint = true;
}
}*/
this.shapes = [].concat(shapes);
@@ -54,7 +55,7 @@ export let Footprint= (function() {
this.overlay = null;
};
Footprint.prototype.setSource = function(source) {
/*Footprint.prototype.setSource = function(source) {
if (this.source) {
this.source.hasFootprint = false;
}
@@ -64,23 +65,14 @@ export let Footprint= (function() {
if (this.source) {
this.source.hasFootprint = true;
}
}
}*/
Footprint.prototype.setCatalog = function(catalog) {
/*Footprint.prototype.setCatalog = function(catalog) {
if (this.source) {
this.source.setCatalog(catalog);
/*for (var s of this.shapes) {
if (!s.color) {
s.setColor(catalog.color);
}
// Selection and hover color are catalog options
s.setSelectionColor(catalog.selectionColor);
s.setHoverColor(catalog.hoverColor);
}*/
}
};
};*/
Footprint.prototype.show = function() {
if (this.isShowing) {
@@ -121,10 +113,10 @@ export let Footprint= (function() {
return;
}
let catalog = this.getCatalog();
/*let catalog = this.getCatalog();
if (catalog) {
catalog.view && catalog.view.requestRedraw();
}
}*/
};
Footprint.prototype.unhover = function() {
@@ -138,11 +130,6 @@ export let Footprint= (function() {
if (this.overlay) {
this.overlay.reportChange();
}
let catalog = this.getCatalog();
if (catalog) {
catalog.view && catalog.view.requestRedraw();
}
};
Footprint.prototype.getLineWidth = function() {
@@ -190,7 +177,7 @@ export let Footprint= (function() {
return hasBeenDrawn;
};
Footprint.prototype.actionClicked = function() {
/*Footprint.prototype.actionClicked = function() {
if (this.source) {
this.source.actionClicked(this);
}
@@ -202,7 +189,7 @@ export let Footprint= (function() {
}
this.shapes.forEach((shape) => shape.deselect())
};
};*/
// If one shape is is stroke then the whole footprint is
Footprint.prototype.isInStroke = function(ctx, view, x, y) {
@@ -213,16 +200,16 @@ export let Footprint= (function() {
return this.shapes.every((shape) => shape.isTooSmall);
};
Footprint.prototype.getCatalog = function() {
/*Footprint.prototype.getCatalog = function() {
return this.source && this.source.catalog;
};
};*/
Footprint.prototype.setOverlay = function(overlay) {
this.overlay = overlay;
};
Footprint.prototype.intersectsBBox = function(x, y, w, h, view) {
if(this.source) {
/*if(this.source) {
let s = this.source;
if (!s.isShowing) {
@@ -250,8 +237,8 @@ export let Footprint= (function() {
if (c.x >= x && c.x <= x + w && c.y >= y && c.y <= y + h) {
return true;
}
}
return false;
}*/
return this.shapes.some((shape) => shape.intersectsBBox(x, y, w, h, view));
};
return Footprint;

View File

@@ -26,7 +26,7 @@ import { ALEvent } from "./events/ALEvent.js";
* @property {Boolean} [perimeter=false] - Draw the perimeter of the MOC only with `options.color`.
* @property {string} [edge=!fill && !perimeter] - Draw the edges of the HEALPix cells with `options.color`.
The HEALPix cell edges compositing the MOC will be drawn if `fill` and `perimeter` are false
* @property {number} [lineWidth=3] - The line width in pixels
* @property {number} [lineWidth=1] - The line width in pixels
* @property {number} [opacity=1.0] - The opacity of the colors
*/
@@ -93,7 +93,7 @@ export let MOC = (function() {
}
this.opacity = Math.max(0, Math.min(1, this.opacity)); // 0 <= this.opacity <= 1
this.lineWidth = options["lineWidth"] || 3;
this.lineWidth = options["lineWidth"] || 1;
//this.proxyCalled = false; // this is a flag to check whether we already tried to load the MOC through the proxy

View File

@@ -66,6 +66,9 @@ export let ProgressiveCat = (function() {
this.selectionColor = options.selectionColor || '#00ff00'; // TODO: to be merged with Catalog
this.hoverColor = options.hoverColor || this.color;
// when footprints are associated to source, do we need to draw the point source as well ?
this.onlyFootprints = options.onlyFootprints ?? true;
// allows for filtering of sources
this.filterFn = options.filter || undefined; // TODO: do the same for catalog
@@ -75,7 +78,6 @@ export let ProgressiveCat = (function() {
// we cache the list of sources in each healpix tile. Key of the cache is norder+'-'+npix
this.sourcesCache = new Utils.LRUCache(256);
this.footprintsCache = new Utils.LRUCache(256);
//added to allow hips catalogue to also use shape functions
this.updateShape(options);
@@ -210,12 +212,11 @@ export let ProgressiveCat = (function() {
newSource.setCatalog(instance);
}
let footprints = instance.computeFootprints(sources);
return [sources, footprints];
instance.computeFootprints(sources);
return sources;
};
ProgressiveCat.prototype = {
setView: function(view, idx) {
var self = this;
this.view = view;
@@ -267,9 +268,8 @@ export let ProgressiveCat = (function() {
url: self.rootUrl + '/' + 'Norder1/Allsky.tsv',
method: 'GET',
success: function(tsv) {
let [sources, footprints] = getSources(self, tsv, self.fields);
let sources = getSources(self, tsv, self.fields);
self.order1Footprints = footprints;
self.order1Sources = sources;
if (self.order2Sources) {
@@ -287,9 +287,8 @@ export let ProgressiveCat = (function() {
url: self.rootUrl + '/' + 'Norder2/Allsky.tsv',
method: 'GET',
success: function(tsv) {
let [sources, footprints] = getSources(self, tsv, self.fields);
let sources = getSources(self, tsv, self.fields);
self.order2Footprints = footprints;
self.order2Sources = sources;
if (self.order1Sources) {
@@ -321,9 +320,8 @@ export let ProgressiveCat = (function() {
self.fields = getFields(self, xml);
let [sources, footprints] = getSources(self, xml.querySelectorAll('CSV').innerText, self.fields);
let sources = getSources(self, xml.querySelectorAll('CSV').innerText, self.fields);
self.order2Footprints = footprints
self.order2Sources = sources
if (self.order3Sources) {
@@ -345,8 +343,7 @@ export let ProgressiveCat = (function() {
method: 'GET',
success: function(text) {
let xml = ProgressiveCat.parser.parseFromString(text, "text/xml")
let [sources, footprints] = getSources(self, xml.querySelectorAll('CSV').innerText, self.fields);
self.order3Footprints = footprints
let sources = getSources(self, xml.querySelectorAll('CSV').innerText, self.fields);
self.order3Sources = sources
if (self.order2Sources) {
@@ -370,7 +367,7 @@ export let ProgressiveCat = (function() {
return;
}
if (this._shapeIsFunction) {
if (this.shapeFn) {
ctx.save();
}
@@ -415,25 +412,17 @@ export let ProgressiveCat = (function() {
}
}
let key, sources, footprints;
let key, sources;
this.tilesInView.forEach((tile) => {
key = tile[0] + '-' + tile[1];
sources = this.sourcesCache.get(key);
footprints = this.footprintsCache.get(key);
if (footprints) {
footprints.forEach((f) => {
f.draw(ctx, this.view)
f.source.tooSmallFootprint = f.isTooSmall();
});
}
if (sources) {
this.drawSources(sources, ctx, width, height);
}
});
if (this._shapeIsFunction) {
if (this.shapeFn) {
ctx.restore();
}
},
@@ -475,6 +464,8 @@ export let ProgressiveCat = (function() {
});
},
getCacheCanvas: Catalog.prototype.getCacheCanvas,
drawSource: Catalog.prototype.drawSource,
getSources: function() {
@@ -502,33 +493,6 @@ export let ProgressiveCat = (function() {
return ret;
},
getFootprints: function() {
var ret = [];
if (this.order1Footprints) {
ret = ret.concat(this.order1Footprints);
}
if (this.order2Footprints) {
ret = ret.concat(this.order2Footprints);
}
if (this.order3Footprints) {
ret = ret.concat(this.order3Footprints);
}
if (this.tilesInView) {
var footprints, key, t;
for (var k=0; k < this.tilesInView.length; k++) {
t = this.tilesInView[k];
key = t[0] + '-' + t[1];
footprints = this.footprintsCache.get(key);
if (footprints) {
ret = ret.concat(footprints);
}
}
}
return ret;
},
deselectAll: function() {
if (this.order1Sources) {
@@ -557,11 +521,6 @@ export let ProgressiveCat = (function() {
for (var k=0; k<sources.length; k++) {
sources[k].deselect();
}
var footprints = this.footprintsCache[key];
for (var k=0; k<footprints.length; k++) {
footprints[k].deselect();
}
}
},
@@ -648,17 +607,15 @@ export let ProgressiveCat = (function() {
method: 'GET',
//dataType: 'jsonp',
success: function(tsv) {
let [sources, footprints] = getSources(self, tsv, self.fields);
let sources = getSources(self, tsv, self.fields);
self.sourcesCache.set(key, sources);
self.footprintsCache.set(key, footprints);
self.view.requestRedraw();
},
error: function() {
// on suppose qu'il s'agit d'une erreur 404
self.sourcesCache.set(key, []);
self.footprintsCache.set(key, []);
}
});
})(this, t[0], t[1]);

View File

@@ -63,12 +63,6 @@ export class Selector {
})
}
setMode(mode) {
if (mode) {
}
}
start(mode, callback) {
this.view.aladin.addStatusBarMessage({
id: 'selector',
@@ -112,9 +106,9 @@ export class Selector {
return;
}
const bbox = selection.bbox();
var objList = [];
var cat, sources, s;
var overlayItems, f;
var objListPerCatalog = [];
if (view.catalogs) {
for (var k = 0; k < view.catalogs.length; k++) {
@@ -124,26 +118,27 @@ export class Selector {
continue;
}
sources = cat.getSources();
for (var l = 0; l < sources.length; l++) {
s = sources[l];
if (!s.isShowing || !s.x || !s.y || s.tooSmallFootprint === false) {
if (!s.isShowing || !s.x || !s.y) {
continue;
}
// footprints
if (s.isFootprint() && s.tooSmallFootprint === false) {
if (s.footprint.intersectsBBox(bbox.x, bbox.y, bbox.w, bbox.h, view)) {
objListPerCatalog.push(s);
}
continue;
}
if (selection.contains(s)) {
objListPerCatalog.push(s);
}
}
// footprints
overlayItems = cat.getFootprints();
if (overlayItems) {
const {x, y, w, h} = selection.bbox();
for (var l = 0; l < overlayItems.length; l++) {
f = overlayItems[l];
if (f.intersectsBBox(x, y, w, h, view)) {
objListPerCatalog.push(f);
}
}
}
if (objListPerCatalog.length > 0) {
objList.push(objListPerCatalog);
@@ -153,7 +148,6 @@ export class Selector {
}
if (view.overlays) {
const {x, y, w, h} = selection.bbox();
for (var k = 0; k < view.overlays.length; k++) {
let overlay = view.overlays[k];
if (!overlay.isShowing) {
@@ -166,7 +160,7 @@ export class Selector {
continue;
}
if (o.intersectsBBox(x, y, w, h, view)) {
if (o.intersectsBBox(bbox.x, bbox.y, bbox.w, bbox.h, view)) {
objList.push([o]);
}
}

View File

@@ -49,6 +49,10 @@ export let Source = (function() {
this.isHovered = false;
};
Source.prototype.setFootprint = function(footprint) {
this.footprint = footprint;
}
Source.prototype.setCatalog = function(catalog) {
this.catalog = catalog;
};
@@ -81,8 +85,13 @@ export let Source = (function() {
if (this.isSelected) {
return;
}
this.isSelected = true;
if (this.footprint) {
this.footprint.select();
}
if (this.catalog) {
this.catalog.reportChange();
}
@@ -92,7 +101,13 @@ export let Source = (function() {
if (! this.isSelected) {
return;
}
this.isSelected = false;
if (this.footprint) {
this.footprint.deselect();
}
if (this.catalog) {
this.catalog.reportChange();
}
@@ -102,7 +117,13 @@ export let Source = (function() {
if (this.isHovered) {
return;
}
this.isHovered = true;
if (this.footprint) {
this.footprint.hover();
}
if (this.catalog) {
this.catalog.reportChange();
}
@@ -113,6 +134,11 @@ export let Source = (function() {
return;
}
this.isHovered = false;
if (this.footprint) {
this.footprint.unhover();
}
if (this.catalog) {
this.catalog.reportChange();
}
@@ -126,6 +152,18 @@ export let Source = (function() {
this.shape = shape;
}
Source.prototype.setColor = function(color) {
this.color = color;
if (this.footprint) {
this.footprint.setColor(color);
}
}
Source.prototype.setSize = function(size) {
this.size = Math.max(size, 1.0);
}
/**
* Simulates a click on the source
*
@@ -177,13 +215,17 @@ export let Source = (function() {
};
Source.prototype.isFootprint = function() {
return false;
return this.footprint !== undefined && this.footprint !== null;
}
Source.prototype.actionOtherObjectClicked = function() {
if (this.catalog && this.catalog.onClick) {
this.deselect();
}
if (this.footprint) {
this.footprint.deselect()
}
};
return Source;

View File

@@ -1141,6 +1141,7 @@ export let View = (function () {
view.setCursor('pointer');
for (let o of closests) {
if (typeof objHoveredFunction === 'function' && (!lastHoveredObject || !lastHoveredObject.includes(o))) {
var ret = objHoveredFunction(o, xymouse);
}
@@ -1604,9 +1605,14 @@ export let View = (function () {
return source;
});
let tableColor = catalog.color;
if (catalog.colorFn) {
tableColor = "white"
}
let table = {
'name': catalog.name,
'color': catalog.color,
'color': tableColor,
'rows': sources,
'fields': catalog.fields,
'showCallback': ObsCore.SHOW_CALLBACKS(this.aladin)
@@ -2201,7 +2207,7 @@ export let View = (function () {
continue;
}
if (s.hasFootprint === true && s.tooSmallFootprint === false) {
if (s.isFootprint() && cat.onlyFootprints && !s.tooSmallFootprint) {
continue;
}
@@ -2228,19 +2234,16 @@ export let View = (function () {
let closests = [];
footprints.forEach((footprint) => {
if (!footprint.source || !footprint.source.tooSmallFootprint) {
const originLineWidth = footprint.getLineWidth();
let spreadedLineWidth = (originLineWidth || 1) + 3;
footprint.setLineWidth(spreadedLineWidth);
if (footprint.isShowing && footprint.isInStroke(ctx, this, x * window.devicePixelRatio, y * window.devicePixelRatio)) {
closests.push(footprint);
}
footprint.setLineWidth(originLineWidth);
const originLineWidth = footprint.getLineWidth();
let spreadedLineWidth = (originLineWidth || 1) + 3;
footprint.setLineWidth(spreadedLineWidth);
if (footprint.isShowing && footprint.isInStroke(ctx, this, x * window.devicePixelRatio, y * window.devicePixelRatio)) {
closests.push(footprint);
}
footprint.setLineWidth(originLineWidth);
})
return closests;
};
@@ -2264,48 +2267,50 @@ export let View = (function () {
if (this.catalogs) {
for (var k = 0; k < this.catalogs.length; k++) {
let catalog = this.catalogs[k];
let footprints = catalog.getFootprints();
closests = closests.concat(this.closestFootprints(footprints, ctx, x, y));
for (var s of catalog.getSources()) {
if (s.isFootprint() && !s.tooSmallFootprint) {
let footprint = s.footprint;
const originLineWidth = footprint.getLineWidth();
let spreadedLineWidth = (originLineWidth || 1) + 3;
footprint.setLineWidth(spreadedLineWidth);
if (footprint.isShowing && footprint.isInStroke(ctx, this, x * window.devicePixelRatio, y * window.devicePixelRatio)) {
closests.push(s);
}
footprint.setLineWidth(originLineWidth);
}
}
}
}
if (!this.objLookup) {
//ctx.lineWidth = pastLineWidth;
return null;
}
//ctx.lineWidth = pastLineWidth;
var dist = Number.POSITIVE_INFINITY;
var closest = null;
//for (var r = 0; r <= maxRadius; r++) {
//closest = dist = null;
for (var dx = -maxRadius; dx <= maxRadius; dx++) {
if (!this.objLookup[x + dx]) {
continue;
}
for (var dy = -maxRadius; dy <= maxRadius; dy++) {
if (this.objLookup[x + dx][y + dy]) {
var d = dx * dx + dy * dy;
if (d < dist) {
dist = d;
closest = this.objLookup[x + dx][y + dy]
} else if (d == dist) {
closest.concat(this.objLookup[x + dx][y + dy])
}
for (var dx = -maxRadius; dx <= maxRadius; dx++) {
if (!this.objLookup[x + dx]) {
continue;
}
for (var dy = -maxRadius; dy <= maxRadius; dy++) {
if (this.objLookup[x + dx][y + dy]) {
var d = dx * dx + dy * dy;
if (d < dist) {
dist = d;
closest = this.objLookup[x + dx][y + dy]
} else if (d == dist) {
closest.concat(this.objLookup[x + dx][y + dy])
}
}
}
}
if (closest && closest.length > 0) {
closests = closests.concat(closest)
}
/*if (closest) {
closests = closests.concat(closest);
}*/
//}
if (closest && closest.length > 0) {
closests = closests.concat(closest)
}
if (closests.length === 0)
return null;

View File

@@ -83,6 +83,7 @@ export class OverlayStackBox extends Box {
sourceSize: 8,
color: "#318d80",
hoverColor: 'red',
onlyFootprints: false,
onClick: "showTable",
shape: (s) => {
let galaxy = ["Seyfert","Seyfert_1", "Seyfert_2","LSB_G","PartofG","RadioG","Gin","GinPair","HII_G","LensedG","BClG","BlueCompG","EmG","GinCl","GinGroup","StarburstG","LINER","AGN", "Galaxy", "GtowardsGroup", "GtowardsCl", "BrightestCG"].some((n) => s.data.main_type.indexOf(n) >= 0);
@@ -304,7 +305,6 @@ export class OverlayStackBox extends Box {
let moc = A.MOCFromURL(url, {
name: file.name,
lineWidth: 3.0,
});
self.aladin.addMOC(moc);
},
@@ -347,7 +347,6 @@ export class OverlayStackBox extends Box {
{ ra, dec, radius },
{
name: "cone",
lineWidth: 3.0,
}
);
self.aladin.addMOC(moc);
@@ -418,7 +417,6 @@ export class OverlayStackBox extends Box {
},
{
name: "rect",
lineWidth: 3.0,
}
);
self.aladin.addMOC(moc);
@@ -463,7 +461,6 @@ export class OverlayStackBox extends Box {
{ ra, dec },
{
name: "poly",
lineWidth: 3.0,
}
);
self.aladin.addMOC(moc);
@@ -1162,9 +1159,14 @@ export class OverlayStackBox extends Box {
}
// retrieve SVG icon, and apply the layer color
let color = overlay.color;
if (overlay.colorFn) {
color = "white"
}
return new Icon({
size: "small",
url: Icon.dataURLFromSVG({ svg, color: overlay.color }),
url: Icon.dataURLFromSVG({ svg, color }),
tooltip,
});
}

View File

@@ -324,10 +324,17 @@ export let Circle = (function() {
};
// From StackOverflow: https://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection
Circle.prototype.intersectsBBox = function(x, y, w, h) {
Circle.prototype.intersectsBBox = function(x, y, w, h, view) {
var centerXyview = view.aladin.world2pix(this.centerRaDec[0], this.centerRaDec[1]);
if (!centerXyview) {
return false;
}
// compute the absolute distance between the middle of the bbox
// and the center of the circle
const circleDistance = {
x: Math.abs(this.center.x - x),
y: Math.abs(this.center.y - y)
x: Math.abs(centerXyview[0] - (x + w/2)),
y: Math.abs(centerXyview[1] - (y + h/2))
};
if (circleDistance.x > (w/2 + this.radius)) { return false; }

View File

@@ -291,6 +291,7 @@ export let Ellipse = (function() {
ctx.globalAlpha = this.opacity;
ctx.beginPath();
this.aPixels = px_per_deg * this.a;
ctx.ellipse(originScreen[0], originScreen[1], px_per_deg * this.a, px_per_deg * this.b, theta, 0, 2*Math.PI, false);
if (!noStroke) {
if (this.fillColor) {
@@ -344,8 +345,31 @@ export let Ellipse = (function() {
return ctx.isPointInStroke(x, y);
};
Ellipse.prototype.intersectsBBox = function(x, y, w, h) {
// todo
Ellipse.prototype.intersectsBBox = function(x, y, w, h, view) {
// TODO: currently the same as Circle where radius = a.
var centerXyview = view.aladin.world2pix(this.centerRaDec[0], this.centerRaDec[1]);
if (!centerXyview) {
return false;
}
// compute the absolute distance between the middle of the bbox
// and the center of the circle
const circleDistance = {
x: Math.abs(centerXyview[0] - (x + w/2)),
y: Math.abs(centerXyview[1] - (y + h/2))
};
if (circleDistance.x > (w/2 + this.aPixels)) { return false; }
if (circleDistance.y > (h/2 + this.aPixels)) { return false; }
if (circleDistance.x <= (w/2)) { return true; }
if (circleDistance.y <= (h/2)) { return true; }
const dx = circleDistance.x - w/2;
const dy = circleDistance.y - h/2;
const cornerDistanceSquared = dx*dx + dy*dy;
return (cornerDistanceSquared <= (this.aPixels*this.aPixels));
};
return Ellipse;

View File

@@ -175,8 +175,29 @@ export let Vector = (function() {
isInStroke: Ellipse.prototype.isInStroke,
intersectsBBox: function(x, y, w, h) {
// todo
lineIntersectsBox: Polyline.prototype.lineIntersectsBox,
intersectsBBox: function(x, y, w, h, view) {
let p1 = [this.ra1, this.dec1];
let p2 = [this.ra2, this.dec2];
let xy1 = view.aladin.world2pix(p1[0], p1[1]);
let xy2 = view.aladin.world2pix(p2[0], p2[1]);
if (!xy1 || !xy2) {
return false;
}
xy1 = {x: xy1[0], y: xy1[1]};
xy2 = {x: xy2[0], y: xy2[1]};
// Check if line segment intersects with the bounding box
if (this.lineIntersectsBox(xy1, xy2, x, y, w, h)) {
return true;
}
return false;
},
};

View File

@@ -72,7 +72,7 @@ export class SAMPConnector {
var params = message["samp.params"];
const {url, name} = params;
let moc = A.MOCFromURL(url, {name, lineWidth: 3});
let moc = A.MOCFromURL(url, {name});
aladin.addMOC(moc);
};