forked from bolidozor/js9
-
Notifications
You must be signed in to change notification settings - Fork 0
/
js9cat.html
executable file
·387 lines (385 loc) · 15.3 KB
/
js9cat.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge;chrome=1" >
<link type="image/x-icon" rel="shortcut icon" href="./favicon.ico">
<link type="text/css" rel="stylesheet" href="js9support.css">
<link type="text/css" rel="stylesheet" href="js9.css">
<script type="text/javascript" src="js9support.min.js"></script>
<script type="text/javascript" src="js9.min.js"></script>
<script type="text/javascript" src="js9plugins.js"></script>
<style type="text/css">
#centerdiv {
width: 512px;
margin-left: auto ;
margin-right: auto ;
}
</style>
<title>JS9 cat</title>
</head>
<body onload="init();">
<script type="text/javascript">
var n = 500;
var inc = 4;
// on an ipad, the click handler reload the page!
var click='ontouchstart' in document.documentElement?'touchstart': 'click';
function init(){
$("#display").on("change", function(evt){
try{doit("display", this.value);}
finally{$("#display").prop('selectedIndex', 0);
return false;}
});
$("#show").on("change", function(evt){
try{doit("show", this.value);}
finally{$("#show").prop('selectedIndex', 0);
return false;}
});
$("#hide").on("change", function(evt){
try{doit("hide", this.value);}
finally{$("#hide").prop('selectedIndex', 0);
return false;}
});
$("#up").on(click, function(evt){
try{doit("up");}
finally{return false;}
});
$("#down").on(click, function(evt){
try{doit("down");}
finally{return false;}
});
$("#left").on(click, function(evt){
try{doit("left");}
finally{return false;}
});
$("#right").on(click, function(evt){
try{doit("right");}
finally{return false;}
});
}
function mkrandom(arr, n, xdim, ydim, shape, color){
var i, x, y;
for(i=0; i<n; i++){
x = Math.random() * xdim;
y = Math.random() * ydim;
if( i % 2 === 0 ){
arr[i] = {x: x, y: y, shape: shape, color: color,
width: 5, height: 2,
data: {tag: sprintf("ebox: %s,%s,%s", x, y, color)}};
} else {
arr[i] = {x: x, y: y,
data: {tag: sprintf("obox: %s,%s", x, y)}};
}
}
}
function mkspirals(arr, n, xcen, ycen, shape, color){
var i, x, y;
var angle_incr = 2 * Math.PI/180;
var cx = xcen;
var cy = ycen;
var outer_rad = 512*0.48;
for(i=0; i<n; i++){
var ratio = i/n;
var angle = i*angle_incr;
var spiral_rad = ratio * outer_rad;
x = cx + Math.cos(angle) * spiral_rad;
y = cy + Math.sin(angle) * spiral_rad;
// if( i < 10 ) console.log("%s: %s %s", i, x, y);
// if( (n - i) < 10 ) console.log("%s: %s %s", i, x, y);
if( i % 2 === 0 ){
arr[i] = {x: x, y: y, shape: shape, color: color, radius: 4,
data: {tag: sprintf("ecir: %s,%s,%s", x, y, color)}};
} else {
arr[i] = {x: x, y: y,
data: {tag: sprintf("ocir: %s,%s", x, y)}};
}
}
}
function doit(what, who){
switch(what){
case "display":
var circles = [];
var boxes = [];
var im = JS9.GetImage();
if( !im ){
JS9.error("please display an image first!");
}
var xdim = Math.max(512, im.raw.width);
var ydim = Math.max(512, im.raw.height);
var xcen = im.raw.width/2;
var ycen = im.raw.height/2;
var boxopts = $.extend(true, {}, JS9.Catalogs.opts);
boxopts.tooltip = "<b>id: $im.id<\/b><br>pos: $xreg.x $xreg.y<br><i>$xreg.data.tag<\/i>";
boxopts.ongroupcreate = function(im, xregs, evt){
var i, nshape, xcen, ycen;
var xtot=0, ytot=0;
nshape = xregs.length;
for(i=0; i<nshape; i++){
xtot += xregs[i].x;
ytot += xregs[i].y;
}
xcen = xtot / nshape;
ycen = ytot / nshape;
console.log("average pos for %s objects: %s,%s",
nshape, xcen, ycen);
}
var ciropts = $.extend(true, {}, JS9.Catalogs.opts);
ciropts.movable = true;
ciropts.onmouseover = function(im, xreg, evt){
console.log("mouseover: %s %s", im.id, xreg.data.tag);
};
ciropts.onmousedown = function(im, xreg, evt){
console.log("mousedown: %s %s", im.id, xreg.data.tag);
};
switch(who){
case "box":
mkrandom(boxes, n, xdim, ydim, "box", "red");
JS9.NewShapeLayer("box", boxopts);
JS9.AddShapes("box", boxes, {color: "yellow"});
break;
break;
case "circle":
mkspirals(circles, n, xcen, ycen, "circle", "black");
JS9.NewShapeLayer("circle", ciropts);
JS9.AddShapes("circle", circles);
break;
case "both":
mkrandom(boxes, n, xdim, ydim, "box", "red");
JS9.NewShapeLayer("box", JS9.Catalogs.opts);
JS9.AddShapes("box", boxes, {color: "yellow"});
mkspirals(circles, n, xcen, ycen, "circle", "blue");
JS9.NewShapeLayer("circle", JS9.Catalogs.opts);
JS9.AddShapes("circle", circles);
break;
}
break;
case "show":
case "hide":
switch(who){
case "both":
JS9.ShowShapeLayer("box", what);
JS9.ShowShapeLayer("circle", what);
break;
default:
JS9.ShowShapeLayer(who, what);
break;
}
break;
case "up":
JS9.ChangeShapes("circle", "all", {dx: 0, dy: inc});
break;
case "down":
JS9.ChangeShapes("circle", "all", {dx: 0, dy: -inc});
break;
case "left":
JS9.ChangeShapes("circle", "all", {dx: -inc, dy: 0});
break;
case "right":
JS9.ChangeShapes("circle", "all", {dx: inc, dy: 0});
break;
}
}
</script>
<center><font size="+1"><b>JS9 Demo: catalogs</b></font></center>
<table cellspacing="15">
<tr valign="top">
<td>
<table cellspacing="0">
<tr valign="top">
<td>
PNG files (converted from FITS):
<ul>
<li> <a href='javascript:JS9.Load("png/casa.png");'>CAS-A (Chandra)</a>
<li> <a href='javascript:JS9.Load("png/snr.png", {colormap:"heat"});'>CTB 109 (Einstein)</a>
<li> <a href='javascript:JS9.Load("png/m13.png", {scale:"linear", colormap:"sls"});'>m13 (via SkyView)</a>
<li> <a href='javascript:JS9.Load("png/i1000.png", {scale:"linear", colormap:"grey"});'>i1000 (v=x*1000+y)</a>
</ul>
</td>
<td>
FITS images and binary tables:
<ul>
<li> <a href='javascript:JS9.Load("fits/3c58.fits");'>3c58 (Chandra)</a>
<li> <a href='javascript:JS9.Load("fits/3c273.fits");'>3c273 (Chandra)</a>
<li> <a href='javascript:JS9.Load("fits/ngkper.fits");'>gkper (Chandra)</a>
<li> <a href='javascript:JS9.Load("fits/ngc1316.fits", {scale:"linear"});'>ngc1316 (AIPS)</a>
</ul>
</td>
</tr>
</table>
<p>
<select id="display">
<option value="" selected="selected" style="display:none">Display</option>
<option value="box">Box Catalog (with tooltips)</option>
<option value="circle">Circle Catalog (event handlers, movable)</option>
<option value="both">Both Catalogs (non-interactive)</option>
</select>
<select id="hide">
<option value="" selected="selected" style="display:none">Hide</option>
<option value="box">Box Catalog</option>
<option value="circle">Circle Catalog</option>
<option value="both">Both Catalogs</option>
</select>
<select id="show">
<option value="" selected="selected" style="display:none">Show</option>
<option value="box">Box Catalog</option>
<option value="circle">Circle Catalog</option>
<option value="both">Both Catalogs</option>
</select>
<p>
<b>Move circle catalog: </b>
<button id="up">Up</button>
<button id="down">Down</button>
<button id="left">Left</button>
<button id="right">Right</button>
<p>
<div class="JS9Menubar"></div>
<div class="JS9"></div>
<p>
</td>
<td>
Catalogs are arrays of JavaScript objects having the following
elements (as well others that you wish to include):
<ul>
<li> x: image x coordinate
<li> y: image y coordinate
<li> shape: "circle", "box", "ellipse", "polyon"
<li> color: color name or hex number
</ul>
In addition, for each shape, the appropriate size and position
parameters can be specified. These are the same as for regions:
<ul>
<li> circle: radius
<li> box: width, height
<li> ellipse: eradius.x, eradius.y
<li> polygon: points
</ul>
Catalogs are added to an image by first creating a new shape layer
and then adding shapes:
<pre>
JS9.NewShapeLayer(catalog_name, opts);
JS9.AddShapes(catalog_name, catalog_array, opts);
</pre>
where <b>catalog_name</b> is an indentifying name for the catalog.
The optional <b>opts</b> parameter in the first call allows you to
specify default options for the new layer. You can set a default
for any property needed by your shape layer. See JS9.Regions.opts
in js9.js for example of the default options for the regions layer.
<p>
The JS9.Catalogs.opts object is also supplied as a possible default
object for new shape layers. It differs from the JS9.Regions.opts
object in that it does not define regions-specific processing (such as
double-click to edit a region parameters). It also makes the new layer
non-interactive: individual shapes cannot be moved, rotated, resized,
or deleted, nor do they respond to events.
<p>
Starting with the JS9.Catalogs.opts object as a default, you can
make the new layer interactive in a few different ways. The first
way is to set the <b>moveable</b> property in the opts object
to <b>true</b>. This will permit individual shapes to be moved,
rotated, resized and deleted. Shapes will also be moveable and
resizeable as a group.
<p>
The second way is to supply one or more event callbacks as properties
to the opts object:
<ul>
<li> <b>onmousedown</b>: function(im, xreg, evt);
<li> <b>onmouseup</b>: function(im, xreg, evt);
<li> <b>onmousemove</b>: function(im, xreg, evt);
<li> <b>onmouseover</b>: function(im, xreg, evt);
<li> <b>onmouseout</b>: function(im, xreg, evt);
</ul>
When the associated mouse event occurs on a shape, these functions
will be called with the following arguments:
<ul>
<li> <b>im</b>: the image handle for the currently displayed image
<li> <b>xreg</b>: the shape object, as described in JS9.GetShapes()
<li> <b>evt</b>: the original event object
</ul>
For example, to define mouseover and mousedown callbacks:
<pre>
opts.onmouseover = function(im, xreg, evt){
console.log("mouseover: %s %s", im.id, xreg.data.tag);
};
opts.onmousedown = function(im, xreg, evt){
console.log("mousedown: %s %s", im.id, xreg.data.tag);
</pre>
Note that the shapes are still not moveable unless you also set
the <b>moveable</b> property.
<p>
In addition to firing callbacks on events for individual shapes, you
can set the <b>ongroupcreate</b> property in the opts object to a
function that will fire when two or more objects are selected into a
group (which is done using the <b>Command</b> key on a Mac,
or <b>Control</b> key everywhere else):
<ul>
<li><b>ongroupcreate</b>: function(im, xregs, evt);
</ul>
The function will be called with the following arguments:
<ul>
<li> <b>im</b>: the image handle for the currently displayed image
<li> <b>xregs</b>: an array of shape objects within the group
<li> <b>evt</b>: the original event object
</ul>
Note that an array of xreg objects is passed in this case instead of
the single "current" object passed in the other event callbacks.
For example:
<pre>
opts.ongroupcreate = function(im, xregs, evt){
var i, nshape, xcen, ycen;
var xtot=0, ytot=0;
nshape = xregs.length;
for(i=0; i<nshape; i++){
xtot += xregs[i].x; ytot += xregs[i].y;
}
xcen = xtot / nshape; ycen = ytot / nshape;
console.log("average pos for %s objects: %s,%s", nshape, xcen, ycen);
}
</pre>
<p>
The final way to make a shape layer interactive is to specify
a <b>tooltip</b> to display when hovering over objects in this
shape layer. This is done by assigning a tooltip format string to
the <b>tooltip</b> property of the opts object. This string can
contain HTML directives, and it also can contain references to
properties in the im, xreg, and evt objects. When the mouse hovers
over an object, a tooltip string is generated by macro-expanding
the values for these properties. The generated tooltip string is
displayed as the inner HTML of the tooltip. When the mouse leaves
the object, the tooltip is hidden.
<p>
For example, consider the following tooltip string:
<pre>
opts.tooltip = "<b>id: $im.id</b><br>pos: $xreg.x $xreg.y<br><i>$xreg.data.tag</i>";
</pre>
Note how properties of the <b>im</b> and <b>xreg</b> objects are
specified with a "$" prefix. When the mouse hovers over an object,
the generated tooltip will display current image id in bold,
followed by that object's x,y pixel position, followed by a
user "tag" property passed in the <b>data</b> object when
the shape was added.
</td>
</tr>
</table>
<p>
JS9 Demos:
<ul>
<li><a href='js9basics.html'>JS9 Demo: the basics</a>
<li><a href='js9bespoke.html'>JS9 Demo: web page control of JS9</a>
<li><a href='js9sizes.html'>JS9 Demo: setting the size of the JS9 display</a>
<li><a href='js9plugins.html'>JS9 Demo: adding plugins to JS9</a>
<li><a href='js9imexam.html'>JS9 Demo: the imexam plugin for JS9</a>
<li><a href='js9blend.html'>JS9 Demo: image blending</a>
<li><a href='js9cat.html'>JS9 Demo: overlaying catalogs</a>
<li><a href='js9panzoom.html'>JS9 Demo: pan and zoom</a>
<li><a href='js9rgb.html'>JS9 Demo: RGB composite images</a>
<li><a href='js9multi.html'>JS9 Demo: independent instances of JS9</a>
<li><a href='js9analysis.html'>JS9 Demo: remote data analysis</a>
<li><a href='js9onchange.html'>JS9 Demo: running tasks when a region changes</a>
<li><a href='js9create.html'>JS9 Demo: creating a JS9 instance dynamically</a>
<li><a href='js9preload.html'>JS9 Demo: preloading images into JS9</a>
<li><a href='js9bitpix.html'>JS9 Demo: displaying different FITS datatypes</a>
<li><a href='js9pngvsfits.html'>JS9 Demo: PNG representation files vs FITS files</a>
</ul>
</body>
</html>