Skip to content

Commit 6468fd5

Browse files
authored
Firefly-1312,1315: Merge pull request #1431 from Caltech-IPAC/FIREFLY-1312-hips-render
Firefly-1312,1315: hips render & Bug Fix: FITS GnomicProjection using cd matrix
2 parents 5e5b88c + a2201bd commit 6468fd5

File tree

4 files changed

+155
-64
lines changed

4 files changed

+155
-64
lines changed

src/firefly/js/visualize/iv/HiPSRenderer.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ const colorId = (plot) => plot?.colorTableId ?? -1;
2222
* @param screenRenderEnabled
2323
* @param hipsColorOps
2424
* @param {boolean} isMaxOrder - true if the order drawing is max order
25-
* @return {{drawTile(*=, *=): undefined, drawTileImmediate(*=, *, *=): void, abort(): void}}
25+
* @param {number} norder
26+
* @param {number} desiredNorder
27+
* @return {Object}
2628
*/
2729
export function makeHipsRenderer(screenRenderParams, totalCnt, isBaseImage, screenRenderEnabled,
28-
hipsColorOps, isMaxOrder) {
30+
hipsColorOps, isMaxOrder, norder, desiredNorder) {
2931

3032
let renderedCnt=0;
3133
let abortRender= false;
@@ -114,7 +116,7 @@ export function makeHipsRenderer(screenRenderParams, totalCnt, isBaseImage, scre
114116
if (abortRender) return;
115117

116118
const tileSize= tile.tileSize || image.width;
117-
drawOneHiPSTile(offscreenCtx, image, tile.devPtCorners, tileSize, {x:tile.dx,y:tile.dy}, tile.nside);
119+
drawOneHiPSTile(offscreenCtx, image, tile.devPtCorners, tileSize, {x:tile.dx,y:tile.dy}, isMaxOrder, norder, desiredNorder);
118120

119121

120122
if (doRenderNow()) renderToScreen();
@@ -124,7 +126,7 @@ export function makeHipsRenderer(screenRenderParams, totalCnt, isBaseImage, scre
124126
renderedCnt++;
125127
if (abortRender) return;
126128
if (tile.devPtCorners.filter( (t) => t).length ===4) {
127-
drawOneHiPSTile(offscreenCtx, emptyTileCanvas, tile.devPtCorners, 512, {x:tile.dx,y:tile.dy}, tile.nside);
129+
drawOneHiPSTile(offscreenCtx, emptyTileCanvas, tile.devPtCorners, 512, {x:tile.dx,y:tile.dy}, isMaxOrder, norder, desiredNorder);
128130
}
129131
else {
130132
console.log('********************* found one');
@@ -149,12 +151,12 @@ export function makeHipsRenderer(screenRenderParams, totalCnt, isBaseImage, scre
149151
if (tile.coordsWrap && cachedAllSkyData) {
150152
tile.subCells?.forEach( (cell) => {
151153
const subImage= cachedAllSkyData.order3Array[cell.tileNumber];
152-
drawOneHiPSTile(offscreenCtx, subImage, cell.devPtCorners, subImage.width, {x:0,y:0}, cell.nside);
154+
drawOneHiPSTile(offscreenCtx, subImage, cell.devPtCorners, subImage.width, {x:0,y:0}, isMaxOrder, norder, desiredNorder);
153155
});
154156
}
155157
else {
156158
const tileSize= tile.tileSize || image.width;
157-
drawOneHiPSTile(offscreenCtx, image, tile.devPtCorners, tileSize, {x:tile.dx,y:tile.dy}, tile.nside);
159+
drawOneHiPSTile(offscreenCtx, image, tile.devPtCorners, tileSize, {x:tile.dx,y:tile.dy}, isMaxOrder, norder, desiredNorder);
158160
}
159161
}
160162
renderedCnt++;
@@ -227,11 +229,10 @@ export function makeHipsRenderer(screenRenderParams, totalCnt, isBaseImage, scre
227229

228230
/**
229231
*
230-
* @param {number} norder
231232
* @param {HiPSAllSkyCacheInfo} cachedAllSky
232233
* @param {Array.<HiPSDeviceTileData>} tilesToLoad
233234
*/
234-
drawAllSky(norder, cachedAllSky, tilesToLoad) {
235+
drawAllSky(cachedAllSky, tilesToLoad) {
235236
if (abortRender) return;
236237
const allSkyAry= norder===3 ? cachedAllSky.order3Array : cachedAllSky.order2Array;
237238
for(let i=0; i<tilesToLoad.length; i++) { // do a classic for loop to increase the fps by 3 or 4

src/firefly/js/visualize/iv/HiPSSingleTileRender.js

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,45 @@
11
/*
22
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
33
*/
4-
54
import {Matrix} from '../../externalSource/transformation-matrix-js/matrix';
65

6+
7+
8+
const makeSource4Triangle= (centerPt, min, max) => {
9+
return [
10+
[{x:max, y:max}, centerPt, {x:max, y:min}], // 3 >
11+
[{x:max, y:min}, centerPt, {x:min, y:min}], // 12 ^
12+
[{x:min, y:max}, centerPt, {x:min, y:min}], // 9 <
13+
[{x:max, y:max}, centerPt, {x:min, y:max}], // 6 v
14+
];
15+
};
16+
17+
18+
/**
19+
* Compute the amount of correction based on how zoom in the display is, The more zoomed in the less correction
20+
* is needed. Too much correction make for distortion
21+
* @param tileSize
22+
* @param norder
23+
* @param desiredNorder
24+
* @param isMaxOrder
25+
* @return {number|number}
26+
*/
27+
function getCorrection(tileSize, norder,desiredNorder,isMaxOrder) {
28+
if (isMaxOrder) {
29+
const amountOver= desiredNorder-norder;
30+
if (amountOver>3) return .0005;
31+
else if (amountOver===2) return .0024;
32+
else if (amountOver===2) return .004;
33+
else if (amountOver===1) return .005;
34+
else return .01;
35+
}
36+
else {
37+
return tileSize < 80 ? .05 : tileSize < 150 ? .035 : .01;
38+
}
39+
}
40+
41+
42+
743
/**
844
* Draw one HiPS tile by breaking it into 2 triangle and draw each. This function follows the aladin's example
945
*
@@ -12,38 +48,79 @@ import {Matrix} from '../../externalSource/transformation-matrix-js/matrix';
1248
* @param {Array.<DevicePt>} cornersAry - array of points of the 4 corners to copy the image to on the destination canvas
1349
* @param {Number} tileSize - width/height of image tile
1450
* @param {DevicePt|{x:number,y:number}} offset - an offset point
15-
* @param {Number} norder
51+
* @param {boolean} isMaxOrder
52+
* @param {number} norder
53+
* @param {number} desiredNorder
1654
*/
17-
export function drawOneHiPSTile(ctx, img, cornersAry, tileSize, offset, norder) {
18-
19-
// const delta = norder<=3 ? 0.2 : 0;
20-
const delta = 0;
21-
// const triangles= window.firefly?.hipsTriangles ?? 4;
22-
const triangles= tileSize < 80 ? 2 : 4;
23-
const correction= tileSize < 80 ? .05 : tileSize < 150 ? .03 : .01;
55+
export function drawOneHiPSTile(ctx, img, cornersAry, tileSize, offset, isMaxOrder, norder, desiredNorder) {
56+
const triangles= norder===2 || (tileSize < 70) ? 2 : 4;
57+
const correction= getCorrection(tileSize,norder,desiredNorder,isMaxOrder);
58+
// correction= window.cor ?? correction;
59+
// window.firefly.debug && console.log(`tri:${triangles}, tileSize:${tileSize}, maxOrder:${isMaxOrder}, ${norder}, ${desiredNorder}, ${correction}`);
2460

2561
if (triangles===2) {
26-
const triangle1= [{x:tileSize-delta, y:tileSize-delta}, {x:tileSize-delta, y:delta}, {x:delta, y:tileSize-delta}];
27-
const triangle2= [ {x:tileSize-delta, y:delta}, {x:delta, y:tileSize-delta}, {x:delta, y:delta} ];
62+
const triangle1= [{x:tileSize, y:tileSize}, {x:tileSize, y:0}, {x:0, y:tileSize}];
63+
const triangle2= [{x:tileSize, y:0}, {x:0, y:tileSize}, {x:0, y:0}];
2864

29-
drawTexturedTriangle(ctx, img, offset, ...triangle1, cornersAry[0], cornersAry[1], cornersAry[3], correction);
30-
drawTexturedTriangle(ctx, img,offset, ...triangle2, cornersAry[1], cornersAry[3], cornersAry[2], correction);
65+
drawTexturedTriangle(ctx, img, offset, ...triangle1, cornersAry[0], cornersAry[1], cornersAry[3], correction, true);
66+
drawTexturedTriangle(ctx, img,offset, ...triangle2, cornersAry[1], cornersAry[3], cornersAry[2], correction, true);
3167
}
3268
else if (triangles===4) {
3369
const mp=tileSize/2;
3470
const cMx= cornersAry.reduce( (total,pt) => total+pt.x, 0)/cornersAry.length;
3571
const cMy= cornersAry.reduce( (total,pt) => total+pt.y, 0)/cornersAry.length;
3672
const cPt= {x:cMx,y:cMy};
3773

38-
const triangle1= [{x:tileSize-delta, y:tileSize-delta}, {x:mp-delta, y:mp-delta}, {x:tileSize-delta, y:delta}];
39-
const triangle2= [{x:tileSize-delta, y:delta}, {x:mp-delta, y:mp-delta}, {x:delta, y:delta}];
40-
const triangle3= [{x:delta, y:tileSize-delta}, {x:mp-delta, y:mp-delta}, {x:delta, y:delta}];
41-
const triangle4= [{x:tileSize-delta, y:tileSize-delta}, {x:mp-delta, y:mp-delta}, {x:delta, y:tileSize-delta}];
74+
const [triangle1, triangle2, triangle3, triangle4]= makeSource4Triangle({x:mp, y:mp}, 0, tileSize);
75+
drawTexturedTriangle(ctx, img, offset, ...triangle1, cornersAry[0], cPt, cornersAry[1], correction, false); // 3 >
76+
drawTexturedTriangle(ctx, img, offset, ...triangle2, cornersAry[1], cPt, cornersAry[2], correction, false); // 12 ^
77+
drawTexturedTriangle(ctx, img, offset, ...triangle3, cornersAry[3], cPt, cornersAry[2], correction, false); // 9 <
78+
drawTexturedTriangle(ctx, img, offset, ...triangle4, cornersAry[0], cPt, cornersAry[3], correction, false); // 6 v
79+
}
80+
else if (triangles===16) { // keep this section around if we have to use it, it is not complete and not tested
81+
// const mp=tileSize/2;
82+
// const cMx= cornersAry.reduce( (total,pt) => total+pt.x, 0)/cornersAry.length;
83+
// const cMy= cornersAry.reduce( (total,pt) => total+pt.y, 0)/cornersAry.length;
84+
// const cPt= {x:cMx,y:cMy};
85+
//
86+
//
87+
//
88+
//
89+
//
90+
// bottom - right
91+
// const sec1cp= mp+mp/2;
92+
// const sec1CenPt= {x:sec1cp, y:sec1cp};
93+
// const triangle1_1= [{x:tileSize, y:tileSize}, sec1CenPt, {x:tileSize, y:mp}]; // 3
94+
// const triangle1_2= [{x:tileSize, y:tileSize}, sec1CenPt, {x:mp, y:tileSize}]; // 6
95+
// const triangle1_3= [{x:mp, y:tileSize}, sec1CenPt, {x:mp, y:mp}]; // 9
96+
// const triangle1_4= [{x:mp, y:mp}, sec1CenPt, {x:tileSize, y:tileSize}]; // 12
4297

43-
drawTexturedTriangle(ctx, img, offset, ...triangle1, cornersAry[0], cPt, cornersAry[1], correction);
44-
drawTexturedTriangle(ctx, img, offset, ...triangle2, cornersAry[1], cPt, cornersAry[2], correction);
45-
drawTexturedTriangle(ctx, img, offset, ...triangle3, cornersAry[3], cPt, cornersAry[2], correction);
46-
drawTexturedTriangle(ctx, img, offset, ...triangle4, cornersAry[0], cPt, cornersAry[3], correction);
98+
// const srcTriangles= [
99+
// ...makeSource4Triangle(mp+(mp/2),mp,tileSize), // bottom right
100+
// ...makeSource4Triangle(mp-(mp/2), mp,tileSize), // top right
101+
// ...makeSource4Triangle(mp+(mp/2), 0,mp), // bottom left
102+
// ...makeSource4Triangle(mp/2, 0,mp), // bottom left
103+
// ];
104+
105+
106+
107+
// top - right
108+
// const sec2cp= mp-mp/2;
109+
// const sec2CenPt= {x:sec2cp,y:sec2cp};
110+
//
111+
//
112+
//
113+
//
114+
//
115+
// // const triangle1= [{x:tileSize-delta, y:tileSize-delta}, {x:mp-delta, y:mp-delta}, {x:tileSize-delta, y:delta}];
116+
// const triangle2= [{x:tileSize-delta, y:delta}, {x:mp-delta, y:mp-delta}, {x:delta, y:delta}];
117+
// const triangle3= [{x:delta, y:tileSize-delta}, {x:mp-delta, y:mp-delta}, {x:delta, y:delta}];
118+
// const triangle4= [{x:tileSize-delta, y:tileSize-delta}, {x:mp-delta, y:mp-delta}, {x:delta, y:tileSize-delta}];
119+
//
120+
// drawTexturedTriangle(ctx, img, offset, ...triangle1, cornersAry[0], cPt, cornersAry[1], correction);
121+
// drawTexturedTriangle(ctx, img, offset, ...triangle2, cornersAry[1], cPt, cornersAry[2], correction);
122+
// drawTexturedTriangle(ctx, img, offset, ...triangle3, cornersAry[3], cPt, cornersAry[2], correction);
123+
// drawTexturedTriangle(ctx, img, offset, ...triangle4, cornersAry[0], cPt, cornersAry[3], correction);
47124
}
48125
}
49126

@@ -52,10 +129,10 @@ const scaleCoeff = 0.01;
52129
/**
53130
* Reproject and draw the part of the image defined by triangle source point 0,1,2 to triangle pt 0,1,2 of the destination image
54131
*
55-
* This started with code from Aladin which took it from demo code http://www.dhteumeuleu.com/lab/image3D.html
132+
* This started with code from Aladin which it took from demo code http://www.dhteumeuleu.com/lab/image3D.html
56133
* it takes a triangle from a source image and maps to a triangle in the target image
57134
* I have modified it to use transformation-matrix-js since the triangle transform is well understood.
58-
* transformation-matrix-js is used to compute the affine transform, triangle conversion affine transform
135+
* transformation-matrix-js is used to compute the affine transform to do the drawing
59136
*
60137
* This is effectively 3d triangle drawing without using web GL.
61138
*
@@ -69,15 +146,20 @@ const scaleCoeff = 0.01;
69146
* @param {Point} pt1 - destination point 1
70147
* @param {Point} pt2 - destination point 2
71148
* @param {number} correction
149+
* @param {boolean} centerPtCorrection - in a 4 triangle case this should be false, you don't want to have correction * internal to the tile
150+
* todo - we we do 16 triangle we need more than a boolean to specify where the correction is applied
72151
*/
73152
function drawTexturedTriangle(ctx, img, offset,
74-
s0, s1, s2, {x:x0, y:y0}, {x:x1, y:y1}, {x:x2, y:y2}, correction= .01) {
153+
s0, s1, s2, {x:x0, y:y0}, {x:x1, y:y1}, {x:x2, y:y2}, correction= .01, centerPtCorrection= false) {
75154
const xc = (x0 + x1 + x2) / 3;
76155
const yc = (y0 + y1 + y2) / 3;
77156

78157
const applyC= (v,c) => ((1+correction) * v - c * correction);
158+
159+
const tgtCenterPt= centerPtCorrection ? [applyC(x1,xc), applyC(y1,yc)] : [x1,y1] ;
79160
const tgtAry= correction ?
80-
[ applyC(x0,xc), applyC(y0,yc), applyC(x1,xc), applyC(y1,yc), applyC(x2,xc), applyC(y2,yc)] :
161+
// [ applyC(x0,xc), applyC(y0,yc), applyC(x1,xc), applyC(y1,yc), applyC(x2,xc), applyC(y2,yc)] :
162+
[ applyC(x0,xc), applyC(y0,yc), ...tgtCenterPt, applyC(x2,xc), applyC(y2,yc)] :
81163
[x0,y0,x1,y1,x2,y2];
82164

83165
const srcPtAry= [s0.x+offset.x, s0.y+offset.y, s1.x+offset.x, s1.y+offset.y, s2.x+offset.x, s2.y+offset.y];

0 commit comments

Comments
 (0)