points to moc/healpix released versions + multi selection

This commit is contained in:
Matthieu Baumann
2024-05-29 19:26:35 +10:00
parent bada1dcecb
commit 93a7c7c642
18 changed files with 290 additions and 186 deletions

View File

@@ -9,9 +9,10 @@
let aladin;
A.init.then(() => {
aladin = A.aladin("#aladin-lite-div", {
target: "12 25 41.512 +12 48 47.2",
inertia: false,
fov: 1,
target: "03 36 31.65 -35 17 43.1",
survey: "CDS/P/DES-DR2/ColorIRG",
fov: 3 / 60,
fullScreen: true,
showContextMenu: true,
showZoomControl: true,
showSettingsControl: true,
@@ -20,7 +21,7 @@
});
// define custom draw function
var hips = A.catalogHiPS(
/*var hips = A.catalogHiPS(
"https://axel.u-strasbg.fr/HiPSCatService/Simbad",
{
onClick: "showTable",
@@ -38,7 +39,24 @@
return A.ellipse(s.ra, s.dec, a / 60, b / 60, theta, { color: "cyan" });
},
}
);
);*/
var hips = A.catalogHiPS(
"https://axel.cds.unistra.fr/HiPSCatService/II/371/des_dr2",
{
onClick: "showTable",
name: "Simbad",
color: "cyan",
hoverColor: "red",
shape: (s) => {
let a = +s.data['Aimg']/3600;
let b = +s.data['Bimg']/3600;
let theta = +s.data['PA'];
return A.ellipse(s.ra, s.dec, a, b, theta, { color: "cyan" });
},
}
)
aladin.addCatalog(hips);
});
</script>

View File

@@ -19,11 +19,11 @@
overlay.addFootprints([
A.polygon([[83.64287, 22.01713], [83.59872, 22.01692], [83.59852, 21.97629], [83.64295, 21.97629]]),
A.polygon([[83.62807, 22.06330], [83.58397, 22.02280], [83.62792, 22.02258]]),
A.ellipse(10.6833, 41.2669, 3.33333/2, 1.1798333/2, 35, {color: 'cyan'}),
A.ellipse(10.6833, 41.2669, 3.33333/2, 1.1798333/2, 10, {color: 'cyan'}),
// NGC 3048
A.ellipse(180.470842, -18.867589, 5.2/120, 3.1/120, 80, {color: 'cyan'}),
A.ellipse(180.470842, -18.867589, 5.2/120, 3.1/120, 10, {color: 'cyan'}),
// NGC 3049
A.ellipse(180.4742, -18.8850, 3.1/120, 1.6/120, 50, {color: 'cyan'}),
A.ellipse(180.4742, -18.8850, 3.1/120, 1.6/120, 10, {color: 'cyan'}),
]);
//overlay.add(); // radius in degrees
});

View File

@@ -16,6 +16,10 @@
var overlay = A.graphicOverlay({lineWidth: 2});
aladin.addOverlay(overlay);
overlay.add(A.polyline([ [2.29452158, 59.14978110], [10.12683778, 56.53733116], [14.1772154, 60.7167403], [21.45396446, 60.23528403], [28.59885697, 63.67010079] ], {color: 'green'}));
aladin.select('rect', (s) => {
console.log(s)
})
});
</script>
</body>

View File

@@ -41,7 +41,7 @@
"preview": "vite preview",
"test:build": "cd src/core && cargo test --release --features webgl2",
"test:unit": "vitest run",
"doc": "jsdoc -d doc --readme README.md src/js && cp aladin-logo.png doc/",
"doc": "jsdoc -d doc --readme README.md src/js src/js/shapes && cp aladin-logo.png doc/",
"doc:dev": "npm run doc && open doc/index.html"
},
"devDependencies": {

View File

@@ -40,13 +40,11 @@ rand = "0.8"
[dependencies.healpix]
package = "cdshealpix"
git = "https://github.com/bmatthieu3/cds-healpix-rust"
branch = "polygonIntersectVertices"
version = "0.6.9"
[dependencies.moclib]
package = "moc"
git = "https://github.com/bmatthieu3/cds-moc-rust"
branch = "cellsWithUnidirectionalNeigs"
version = "0.14.2"
[dependencies.serde]
version = "^1.0.183"

View File

@@ -3,7 +3,11 @@ use crate::math::PI;
use crate::math::{self, lonlat::LonLat};
use cgmath::{Vector3, Vector4};
use moclib::{moc::range::RangeMOC, qty::Hpx, ranges::SNORanges};
use moclib::{
moc::range::{CellSelection, RangeMOC},
qty::Hpx,
ranges::SNORanges,
};
pub type Smoc = RangeMOC<u64, Hpx<u64>>;
use crate::healpix::cell::HEALPixCell;
@@ -29,8 +33,12 @@ impl HEALPixCoverage {
.collect::<Vec<_>>();
let LonLatT(in_lon, in_lat) = inside.lonlat();
let moc =
RangeMOC::from_polygon_with_control_point(&lonlat[..], (in_lon.0, in_lat.0), depth);
let moc = RangeMOC::from_polygon_with_control_point(
&lonlat[..],
(in_lon.0, in_lat.0),
depth,
CellSelection::All,
);
HEALPixCoverage(moc)
}
@@ -64,6 +72,7 @@ impl HEALPixCoverage {
rad,
depth,
0,
CellSelection::All,
))
}
}

View File

@@ -1,7 +1,7 @@
use crate::healpix::coverage::HEALPixCoverage;
use moclib::elem::cell::Cell;
use moclib::moc::range::CellAndNeighs;
//use moclib::moc::range::CellAndNeighs;
use moclib::moc::RangeMOCIntoIterator;
use moclib::moc::RangeMOCIterator;
@@ -91,11 +91,10 @@ impl NodeEdgeNeigs {
1 << delta_depth
}
}
pub(super) struct G {
/*pub(super) struct G {
nodes: Vec<NodeEdgeNeigs>,
}
use crate::renderable::coverage::mode::Node;
impl G {
pub(super) fn new(moc: &HEALPixCoverage) -> Self {
let mut nodes: Vec<_> = (&moc.0)
@@ -294,3 +293,4 @@ fn find_neig_dir(mut cell: HEALPixCell, mut neig: HEALPixCell) -> Option<Ordinal
None
}
*/

View File

@@ -17,11 +17,17 @@ use crate::renderable::line::RasterizedLineRenderer;
use al_api::color::ColorRGBA;
use al_api::coo_system::CooSystem;
use moclib::moc::RangeMOCIntoIterator;
use moclib::moc::RangeMOCIterator;
use super::mode::Node;
use crate::HEALPixCell;
use cgmath::Vector2;
use wasm_bindgen::prelude::*;
use healpix::compass_point::OrdinalMap;
pub struct MOC {
pub sky_fraction: f32,
pub max_order: u8,
@@ -149,11 +155,34 @@ pub enum RenderModeType {
impl MOCIntern {
fn new(moc: &HEALPixCoverage, mode: RenderModeType) -> Self {
let nodes = match mode {
/*let nodes = match mode {
RenderModeType::Edge { .. } => super::mode::edge::Edge::build(moc),
RenderModeType::Filled { .. } => super::mode::filled::Fill::build(moc),
RenderModeType::Perimeter { .. } => super::mode::perimeter::Perimeter::build(moc),
};
};*/
let mut sides = OrdinalMap::new();
sides.put(healpix::compass_point::Ordinal::SE, 1);
sides.put(healpix::compass_point::Ordinal::SW, 1);
sides.put(healpix::compass_point::Ordinal::NE, 1);
sides.put(healpix::compass_point::Ordinal::NW, 1);
let nodes = (&moc.0)
.into_range_moc_iter()
.cells()
.flat_map(|cell| {
let cell = HEALPixCell(cell.depth, cell.idx);
let dd = if 3 >= cell.depth() {
3 - cell.depth()
} else {
0
};
cell.get_tile_cells(dd)
})
.map(|cell| Node {
vertices: cell.path_along_sides(&sides),
cell,
})
.collect::<Vec<_>>();
let hpx_idx_vec = IdxVec::from_hpx_cells(nodes.iter().map(|n| &n.cell));

View File

@@ -4,18 +4,9 @@ use super::RenderMode;
use crate::HEALPixCoverage;
use healpix::{
compass_point::{Ordinal, OrdinalMap},
};
use healpix::compass_point::{Ordinal, OrdinalMap};
/*
pub struct Edge;
@@ -198,3 +189,4 @@ impl RenderMode for Edge {
.collect()
}
}
*/

View File

@@ -4,8 +4,9 @@ use super::RenderMode;
use crate::HEALPixCoverage;
use healpix::compass_point::{Ordinal, OrdinalMap};
/*
use super::super::graph::G;
pub struct Fill;
impl RenderMode for Fill {
@@ -189,3 +190,4 @@ impl RenderMode for Fill {
.collect()
}
}
*/

View File

@@ -1,17 +1,12 @@
use super::Node;
use super::RenderMode;
use crate::healpix::cell::HEALPixCell;
use healpix::{
compass_point::{Ordinal, OrdinalMap},
};
use healpix::compass_point::{Ordinal, OrdinalMap};
use moclib::elem::cell::Cell;
use crate::HEALPixCoverage;
use moclib::moc::range::CellAndEdges;
/*
pub struct Perimeter;
impl RenderMode for Perimeter {
@@ -43,3 +38,4 @@ impl RenderMode for Perimeter {
.collect()
}
}
*/

View File

@@ -104,7 +104,9 @@
}
.aladin-measurement-div table tr td a {
display: block;
color: green;
}
.aladin-measurement-div table tr td a:hover {
color: greenyellow;
}

View File

@@ -69,6 +69,9 @@ import { SimbadPointer } from "./gui/Button/SimbadPointer";
import { OverlayStackButton } from "./gui/Button/OverlayStack";
import { GridEnabler } from "./gui/Button/GridEnabler";
import { CooFrame } from "./gui/Input/CooFrame";
import { Circle } from "./shapes/Circle";
import { Ellipse } from "./shapes/Ellipse";
import { Polyline } from "./shapes/Polyline";
/**
* @typedef {Object} AladinOptions
@@ -1981,7 +1984,34 @@ aladin.on("positionChanged", ({ra, dec}) => {
new ALEvent(alEventName).listenedBy(this.aladinDiv, customFn);
};
/**
* Select specific objects in the view
*
* @memberof Aladin
* @param {?Array.<Source, Footprint, Circle, Ellipse, Polyline, Line>} objects - If null is passed then nothing will be selected and sources already selected will be deselected
*/
Aladin.prototype.selectObjects = function (objects) {
if (!objects) {
this.view.unselectObjects();
return;
}
let objListPerCatalog = {};
for (let o of objects) {
let cat = o.getCatalog();
if (cat) {
let objList = objListPerCatalog[cat.name];
if (!objList) {
objList = [];
} else {
objList.push(o);
}
}
}
objects = Object.values(objListPerCatalog);
console.log(objects);
this.view.selectObjects(objects);
};

View File

@@ -166,7 +166,9 @@ export let AladinUtils = {
},
/**
* @function degreesToString
* @function
* @memberof AladinUtils
* @name degreesToString
* Convert a number in degrees into a string<br>
*
* @param numberDegrees number in degrees (integer or decimal)

View File

@@ -372,38 +372,43 @@ export let ProgressiveCat = (function() {
}
// Order must be >= 0
if (this.order1Footprints) {
this.order1Footprints.forEach((f) => {
f.draw(ctx, this.view);
f.source.tooSmallFootprint = f.isTooSmall();
});
}
if (this.order1Sources) {
this.drawSources(this.order1Sources, ctx, width, height);
}
if (this.order1Footprints) {
this.order1Footprints.forEach((f) => {
f.draw(ctx, this.view)
});
}
if (this.view.realNorder >= 1) {
if (this.order2Sources) {
this.drawSources(this.order2Sources, ctx, width, height);
}
if (this.order2Footprints) {
this.order2Footprints.forEach((f) => {
f.draw(ctx, this.view)
f.source.tooSmallFootprint = f.isTooSmall();
});
}
if (this.order2Sources) {
this.drawSources(this.order2Sources, ctx, width, height);
}
}
// For old allsky, tilesInView refers to tiles at orders 4..
// For new allsky, tilesInView will contains order3 sources
if (this.maxOrderAllsky === 3) {
if (this.view.realNorder >= 2) {
if (this.order3Sources) {
this.drawSources(this.order3Sources, ctx, width, height);
}
if (this.order3Footprints) {
this.order3Footprints.forEach((f) => {
f.draw(ctx, this.view)
f.source.tooSmallFootprint = f.isTooSmall();
});
}
if (this.order3Sources) {
this.drawSources(this.order3Sources, ctx, width, height);
}
}
}
@@ -413,15 +418,16 @@ export let ProgressiveCat = (function() {
sources = this.sourcesCache.get(key);
footprints = this.footprintsCache.get(key);
if (sources) {
this.drawSources(sources, ctx, width, height);
}
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) {

View File

@@ -547,38 +547,41 @@ export let View = (function () {
// Deselect objects if any
view.unselectObjects();
if (objs) {
var o = objs[0];
// footprint selection code adapted from Fabrizio Giordano dev. from Serco for ESA/ESDC
if (o.marker) {
// could be factorized in Source.actionClicked
view.aladin.popup.setTitle(o.popupTitle);
view.aladin.popup.setText(o.popupDesc);
view.aladin.popup.setSource(o);
view.aladin.popup.show();
}
else {
if (view.lastClickedObject) {
view.lastClickedObject.actionOtherObjectClicked && view.lastClickedObject.actionOtherObjectClicked();
}
}
// show measurements
if (o.actionClicked) {
o.actionClicked();
}
var objClickedFunction = view.aladin.callbacksByEventName['objectClicked'];
(typeof objClickedFunction === 'function') && objClickedFunction(o, xy);
var footprintClickedFunction = view.aladin.callbacksByEventName['footprintClicked'];
if (o.isFootprint()) {
var footprintClickedFunction = view.aladin.callbacksByEventName['footprintClicked'];
if (typeof footprintClickedFunction === 'function' && o != view.lastClickedObject) {
var ret = footprintClickedFunction(o, xy);
for (let o of objs) {
// footprint selection code adapted from Fabrizio Giordano dev. from Serco for ESA/ESDC
if (o.marker) {
// could be factorized in Source.actionClicked
view.aladin.popup.setTitle(o.popupTitle);
view.aladin.popup.setText(o.popupDesc);
view.aladin.popup.setSource(o);
view.aladin.popup.show();
}
/*else {
if (view.lastClickedObject) {
view.lastClickedObject.actionOtherObjectClicked
view.lastClickedObject.actionOtherObjectClicked();
}
}*/
// show measurements
/*if (o.actionClicked) {
o.actionClicked();
}*/
(typeof objClickedFunction === 'function') && objClickedFunction(o, xy);
if (o.isFootprint()) {
if (typeof footprintClickedFunction === 'function' && (!view.lastClickedObject || !view.lastClickedObject.includes(o))) {
footprintClickedFunction(o, xy);
}
}
}
view.lastClickedObject = o;
view.selectObjects([objs]);
view.lastClickedObject = objs;
} else {
// If there is a past clicked object
if (view.lastClickedObject) {
@@ -587,13 +590,14 @@ export let View = (function () {
view.aladin.popup.hide();
// Deselect the last clicked object
if (view.lastClickedObject instanceof Ellipse || view.lastClickedObject instanceof Circle || view.lastClickedObject instanceof Polyline) {
/*if (view.lastClickedObject instanceof Ellipse || view.lastClickedObject instanceof Circle || view.lastClickedObject instanceof Polyline) {
view.lastClickedObject.deselect();
} else {
// Case where lastClickedObject is a Source
view.lastClickedObject.actionOtherObjectClicked();
}
}*/
// TODO: do we need to keep that triggering ?
var objClickedFunction = view.aladin.callbacksByEventName['objectClicked'];
(typeof objClickedFunction === 'function') && objClickedFunction(null, xy);
@@ -968,48 +972,63 @@ export let View = (function () {
// closestObjects is very costly, we would like to not do it
// especially if the objectHovered function is not defined.
var closest = view.closestObjects(xymouse.x, xymouse.y, 5);
var closests = view.closestObjects(xymouse.x, xymouse.y, 5);
if (closest) {
let o = closest[0];
if (closests) {
var objHoveredFunction = view.aladin.callbacksByEventName['objectHovered'];
var footprintHoveredFunction = view.aladin.callbacksByEventName['footprintHovered'];
view.setCursor('pointer');
if (typeof objHoveredFunction === 'function' && o != lastHoveredObject) {
var ret = objHoveredFunction(o, xymouse);
}
if (o.isFootprint()) {
if (typeof footprintHoveredFunction === 'function' && o != lastHoveredObject) {
var ret = footprintHoveredFunction(o, xymouse);
for (let o of closests) {
if (typeof objHoveredFunction === 'function' && (!lastHoveredObject || !lastHoveredObject.includes(o))) {
var ret = objHoveredFunction(o, xymouse);
}
if (o.isFootprint()) {
if (typeof footprintHoveredFunction === 'function' && (!lastHoveredObject || !lastHoveredObject.includes(o))) {
var ret = footprintHoveredFunction(o, xymouse);
}
}
if (!lastHoveredObject || !lastHoveredObject.includes(o)) {
o.hover();
}
}
if (lastHoveredObject && o != lastHoveredObject) {
lastHoveredObject.unhover();
// unhover the objects in lastHoveredObjects that are not in closest anymore
if (lastHoveredObject) {
var objHoveredStopFunction = view.aladin.callbacksByEventName['objectHoveredStop'];
if (typeof objHoveredStopFunction === 'function') {
objHoveredStopFunction(lastHoveredObject, xymouse);
for (let lho of lastHoveredObject) {
if (!closests.includes(lho)) {
lho.unhover();
if (typeof objHoveredStopFunction === 'function') {
objHoveredStopFunction(lho, xymouse);
}
}
}
}
if (o != lastHoveredObject) {
o.hover();
}
lastHoveredObject = o;
lastHoveredObject = closests;
} else {
view.setCursor('default');
var objHoveredStopFunction = view.aladin.callbacksByEventName['objectHoveredStop'];
if (lastHoveredObject) {
if (typeof objHoveredStopFunction === 'function') {
var objHoveredStopFunction = view.aladin.callbacksByEventName['objectHoveredStop'];
/*if (typeof objHoveredStopFunction === 'function') {
// call callback function to notify we left the hovered object
var ret = objHoveredStopFunction(lastHoveredObject, xymouse);
}
lastHoveredObject.unhover();
lastHoveredObject.unhover();*/
for (let lho of lastHoveredObject) {
lho.unhover();
if (typeof objHoveredStopFunction === 'function') {
objHoveredStopFunction(lho, xymouse);
}
}
}
lastHoveredObject = null;
@@ -1406,42 +1425,47 @@ export let View = (function () {
this.unselectObjects();
if (Array.isArray(selection)) {
this.selection = [selection];
this.selection = selection;
} else {
// select the new
this.selection = Selector.getObjects(selection, this);
}
if (this.selection.length > 0) {
this.selection.forEach((objListPerCatalog) => {
objListPerCatalog.forEach((obj) => obj.select())
objListPerCatalog.forEach((obj) => {
obj.select()
})
});
let tables = this.selection.map((objList) => {
// Get the catalog containing that list of objects
let catalog = objList[0].getCatalog();
let tables = this.selection
.filter(objList => {
return objList[0].getCatalog;
})
.map(objList => {
// Get the catalog containing that list of objects
let catalog = objList[0].getCatalog();
let source;
let sources = objList.map((o) => {
if (o instanceof Footprint) {
source = o.source;
} else {
source = o;
}
return source;
});
let table = {
'name': catalog.name,
'color': catalog.color,
'rows': sources,
'fields': catalog.fields,
'showCallback': ObsCore.SHOW_CALLBACKS(this.aladin)
};
return table;
})
let source;
let sources = objList.map((o) => {
if (o instanceof Footprint) {
source = o.source;
} else {
source = o;
}
return source;
});
let table = {
'name': catalog.name,
'color': catalog.color,
'rows': sources,
'fields': catalog.fields,
'showCallback': ObsCore.SHOW_CALLBACKS(this.aladin)
};
return table;
})
this.aladin.measurementTable.showMeasurement(tables);
let a = this.aladin;
@@ -2019,8 +2043,8 @@ export let View = (function () {
return null;
}
let closests = [];
let closest = null;
footprints.forEach((footprint) => {
if (!footprint.source || !footprint.source.tooSmallFootprint) {
// Hidden footprints are not considered
@@ -2029,16 +2053,15 @@ export let View = (function () {
footprint.setLineWidth(10.0);
if (footprint.isShowing && footprint.isInStroke(ctx, this, x * window.devicePixelRatio, y * window.devicePixelRatio)) {
closest = footprint;
if (closest) {
closests.push(closest);
}
}
footprint.setLineWidth(lineWidth);
if (closest) {
return closest;
}
}
})
return closest;
return closests;
};
// return closest object within a radius of maxRadius pixels. maxRadius is an integer
@@ -2050,15 +2073,12 @@ export let View = (function () {
// this makes footprint selection easier as the catch-zone is larger
//let pastLineWidth = ctx.lineWidth;
let closests = [];
if (this.overlays) {
for (var k = 0; k < this.overlays.length; k++) {
overlay = this.overlays[k];
let closest = this.closestFootprints(overlay.overlayItems, ctx, x, y);
if (closest) {
//ctx.lineWidth = pastLineWidth;
return [closest];
}
closests = closests.concat(this.closestFootprints(overlay.overlayItems, ctx, x, y));
}
}
@@ -2068,11 +2088,7 @@ export let View = (function () {
let catalog = this.catalogs[k];
let footprints = catalog.getFootprints();
let closest = this.closestFootprints(footprints, ctx, x, y);
if (closest) {
//ctx.lineWidth = pastLineWidth;
return [closest];
}
closests = closests.concat(this.closestFootprints(footprints, ctx, x, y));
}
}
@@ -2083,28 +2099,34 @@ export let View = (function () {
//ctx.lineWidth = pastLineWidth;
var closest, dist;
for (var r = 0; r <= maxRadius; r++) {
closest = dist = null;
//var closest, dist;
//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 (!closest || d < dist) {
//var d = dx * dx + dy * dy;
/*if (!closest || d < dist) {
closest = this.objLookup[x + dx][y + dy];
dist = d;
}
//dist = d;
}*/
closests = closests.concat(this.objLookup[x + dx][y + dy])
}
}
}
if (closest) {
return closest;
}
}
return null;
/*if (closest) {
closests = closests.concat(closest);
}*/
//}
if (closests.length === 0)
return null;
return closests;
};
return View;

View File

@@ -31,26 +31,7 @@
import { Utils } from "./../Utils";
import { GraphicOverlay } from "./../Overlay.js";
/**
* @typedef {Object} ShapeOptions
* @description Options for describing a shape
*
* @property {Object} options - Configuration options for the shape.
* @property {string} [options.color] - The color of the shape
* @property {string} [options.fill=false] - Fill the shape with fillColor
* @property {string} [options.fillColor] - A filling color for the shape
* @property {number} [options.lineWidth=2] - The line width in pixels
* @property {number} [options.opacity=1] - The opacity, between 0 (totally transparent) and 1 (totally opaque)
* @property {string} [options.selectionColor='#00ff00'] - A selection color
* @property {string} [options.hoverColor] - A hovered color
*/
/**
* Represents an ellipse shape
*
* @namespace
* @typedef {Object} Ellipse
*/
export let Ellipse = (function() {
/**
* Constructor function for creating a new ellipse.
@@ -58,9 +39,9 @@ export let Ellipse = (function() {
* @constructor
* @memberof Ellipse
* @param {number[]} centerRaDec - right-ascension/declination 2-tuple of the ellipse's center in degrees
* @param {number} a - semi-major axis length in degrees
* @param {number} b - semi-minor axis length in degrees
* @param {number} theta - angle of the ellipse in degrees
* @param {number} a - half-major axis length in degrees
* @param {number} b - half-minor axis length in degrees
* @param {number} theta - angle of the ellipse in degrees. Origin aligns the ellipsis' major axis with the north pole. Positive angle points towards the east.
* @param {ShapeOptions} options - Configuration options for the ellipse
*
* @returns {Ellipse} - The ellipse shape object
@@ -230,7 +211,6 @@ export let Ellipse = (function() {
return true;
}
// TODO
Ellipse.prototype.draw = function(ctx, view, noStroke, noSmallCheck) {
if (! this.isShowing) {
return false;

View File

@@ -37,6 +37,20 @@ import { Utils } from '../Utils';
import { GraphicOverlay } from "../Overlay.js";
import { ProjectionEnum } from "../ProjectionEnum.js";
/**
* @typedef {Object} ShapeOptions
* @description Options for describing a shape
*
* @property {Object} options - Configuration options for the shape.
* @property {string} [options.color] - The color of the shape
* @property {string} [options.fill=false] - Fill the shape with fillColor
* @property {string} [options.fillColor] - A filling color for the shape
* @property {number} [options.lineWidth=3] - The line width in pixels
* @property {number} [options.opacity=1] - The opacity, between 0 (totally transparent) and 1 (totally opaque)
* @property {string} [options.selectionColor='#00ff00'] - A selection color
* @property {string} [options.hoverColor] - A hovered color
*/
/**
* Represents a polyline shape
*