From f34bc8bd410a932aa8f80df9cf1ed8f6eb199cd7 Mon Sep 17 00:00:00 2001 From: roby Date: Wed, 23 Sep 2026 15:49:17 -0600 Subject: [PATCH 1/2] Firefly-2020: render HiPS more accuratly --- src/firefly/js/drawingLayers/hpx/HpxDraw.js | 4 +- src/firefly/js/tables/HpxIndexCntlr.js | 8 +- src/firefly/js/visualize/HiPSUtil.js | 10 ++ src/firefly/js/visualize/WebPlot.js | 3 +- src/firefly/js/visualize/draw/MocObj.js | 5 +- src/firefly/js/visualize/iv/HiPSCellFinder.js | 161 ++++++++++++++---- src/firefly/js/visualize/iv/HiPSRenderer.js | 43 +++-- .../js/visualize/iv/TileDrawHelper.jsx | 2 +- src/firefly/js/visualize/task/ZoomTask.js | 6 +- 9 files changed, 169 insertions(+), 73 deletions(-) diff --git a/src/firefly/js/drawingLayers/hpx/HpxDraw.js b/src/firefly/js/drawingLayers/hpx/HpxDraw.js index 612158263b..1e02a47b08 100644 --- a/src/firefly/js/drawingLayers/hpx/HpxDraw.js +++ b/src/firefly/js/drawingLayers/hpx/HpxDraw.js @@ -1,5 +1,5 @@ import chroma from 'chroma-js'; -import {getHistgramForNorder, getProGradeTilePixels, getTile} from '../../tables/HpxIndexCntlr'; +import {getHistgramForNorder, getTile} from '../../tables/HpxIndexCntlr'; import {getBWBackground} from '../../util/Color'; import CoordSys from '../../visualize/CoordSys'; import {TextLocation} from '../../visualize/draw/DrawingDef'; @@ -7,7 +7,7 @@ import {DrawSymbol} from '../../visualize/draw/DrawSymbol'; import FootprintObj from '../../visualize/draw/FootprintObj'; import PointDataObj from '../../visualize/draw/PointDataObj'; import ShapeDataObj, {UnitType} from '../../visualize/draw/ShapeDataObj'; -import {getCornersForCell} from '../../visualize/HiPSUtil'; +import {getCornersForCell, getProGradeTilePixels} from '../../visualize/HiPSUtil'; import {makeDevicePt} from '../../visualize/Point'; import {computeSimpleDistance, computeSimpleSlope, lineIntersect2, RtoD} from '../../visualize/VisUtil'; import { diff --git a/src/firefly/js/tables/HpxIndexCntlr.js b/src/firefly/js/tables/HpxIndexCntlr.js index bb6724401e..a236dd54cf 100644 --- a/src/firefly/js/tables/HpxIndexCntlr.js +++ b/src/firefly/js/tables/HpxIndexCntlr.js @@ -7,8 +7,9 @@ import {ang2pixNest, radecToPolar} from '../externalSource/aladinProj/HealpixInd import {logger} from '../util/Logger'; import {blockWhileAsyncIdWaiting, synchronizeAsyncFunctionById} from '../util/SynchronizeAsync'; import {createBackgroundRunner, isDefined} from '../util/WebUtil'; -import {DEFAULT_COVERAGE_PLOT_ID} from '../visualize/VisConst'; +import {getProGradeTilePixels} from '../visualize/HiPSUtil'; import {makeWorldPt} from '../visualize/Point'; +import {DEFAULT_COVERAGE_PLOT_ID} from '../visualize/VisConst'; import {convertCelestial} from '../visualize/VisUtil'; import {findTableCenterColumns, makeWorldPtUsingCenterColumns} from '../voAnalyzer/TableAnalysis'; import {getTableModel} from '../voAnalyzer/VoCoreUtils'; @@ -513,11 +514,6 @@ export function onOrderDataReady(tbl_id) { -export function getProGradeTilePixels(pixel) { - const base= pixel*4; - return [base,base+1,base+2,base+3]; -} - export const getRetroGradeIpix= (ipix, retroCnt=1) => retroCnt ? Math.trunc(ipix/(4**retroCnt)) : ipix; const tableRunIds= {}; diff --git a/src/firefly/js/visualize/HiPSUtil.js b/src/firefly/js/visualize/HiPSUtil.js index 35a34e5f8d..fa12023b5f 100644 --- a/src/firefly/js/visualize/HiPSUtil.js +++ b/src/firefly/js/visualize/HiPSUtil.js @@ -786,3 +786,13 @@ function getHipsPixelCutRangeValues(plot) { } return defaultRv; } + +/** + * get the 4 child pixels at the prograded norder + * @param {number} pixel + * @return {Array.} array of 4 pixels + */ +export function getProGradeTilePixels(pixel) { + const base = pixel * 4; + return [base, base + 1, base + 2, base + 3]; +} diff --git a/src/firefly/js/visualize/WebPlot.js b/src/firefly/js/visualize/WebPlot.js index 58a268b92c..bd4ce4892c 100644 --- a/src/firefly/js/visualize/WebPlot.js +++ b/src/firefly/js/visualize/WebPlot.js @@ -421,7 +421,7 @@ function getAllHeaderAndWlInfo(cubeCtx, wpInit, plotState) { allWlMap[bStr]=processAllWavelengthAltWcs(headerAry[b.value], bandWlTable, idx>0); }); - plotState.getBands().forEach( (b,idx) => { + plotState.getBands().forEach( (b) => { const bStr= b.toString(); if (wlDataAry[b.value]) { allWlMap[bStr]['']= wlDataAry[b.value]; @@ -592,7 +592,6 @@ export const WebPlot= { const hipsPlot= { //HiPS specific - nside: 3, colorTableId: NO_COLOR_TABLE, hipsUrlRoot, dataCoordSys : hipsCoordSys, diff --git a/src/firefly/js/visualize/draw/MocObj.js b/src/firefly/js/visualize/draw/MocObj.js index 4fee30cdc6..6c79ef439d 100644 --- a/src/firefly/js/visualize/draw/MocObj.js +++ b/src/firefly/js/visualize/draw/MocObj.js @@ -1,5 +1,4 @@ import {getAppOptions} from '../../api/ApiUtil.js'; -import {getProGradeTilePixels} from '../../tables/HpxIndexCntlr'; import {logger} from '../../util/Logger'; import DrawObj from './DrawObj'; import {makeWorldPt} from '../Point.js'; @@ -10,7 +9,9 @@ import { getMocOrderIndex, getMocSidePointsNuniq, getCornerForPix, getMocNuniq, isTileVisibleByPosition, initSidePoints, NSIDE4, getSidePointsNorder, NSIDE2 } from '../HiPSMocUtil.js'; -import {getHealpixCornerTool, getAllVisibleHiPSCells, getPointMaxSide, getHiPSNorderlevel} from '../HiPSUtil.js'; +import { + getHealpixCornerTool, getAllVisibleHiPSCells, getPointMaxSide, getHiPSNorderlevel, getProGradeTilePixels +} from '../HiPSUtil.js'; import DrawOp from './DrawOp.js'; import CsysConverter, {CysConverter} from '../CsysConverter.js'; import {Style, TextLocation,DEFAULT_FONT_SIZE} from './DrawingDef.js'; diff --git a/src/firefly/js/visualize/iv/HiPSCellFinder.js b/src/firefly/js/visualize/iv/HiPSCellFinder.js index 55a915074d..530f96a09e 100644 --- a/src/firefly/js/visualize/iv/HiPSCellFinder.js +++ b/src/firefly/js/visualize/iv/HiPSCellFinder.js @@ -1,11 +1,13 @@ /* * License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt */ -import {getCornersForCell, getVisibleHiPSCells, tileCoordsWrap} from 'firefly/visualize/HiPSUtil.js'; -import {isHiPSAitoff} from 'firefly/visualize/WebPlot.js'; -import {isQuadTileOnScreen} from 'firefly/visualize/iv/TileDrawHelper.jsx'; -import {makeDevicePt} from 'firefly/visualize/Point.js'; -import {CysConverter} from 'firefly/api/ApiUtilImage.jsx'; +import { getHealpixCornerTool, getProGradeTilePixels, getVisibleHiPSCells, tileCoordsWrap} from '../HiPSUtil.js'; +import {isHiPSAitoff} from '../WebPlot.js'; +import {isQuadTileOnScreen} from './TileDrawHelper.jsx'; +import {makeDevicePt} from '../Point'; +import {CysConverter} from '../CsysConverter'; + +const imageOffsets= [[0,0],[0,1],[1,0],[1,1]]; // which half of the parent tile image, in units of the child tile size /** * @global @@ -13,11 +15,11 @@ import {CysConverter} from 'firefly/api/ApiUtilImage.jsx'; * @typedef {Object} HiPSDeviceTileData * * @prop {number} tileNumber - HiPS pixel number - * @prop {number} nside - healpix level + * @prop {number} norder - healpix order * @prop {Array.} devPtCorners - the target corners of the tile in device coordinates - * @prop {number} dx - x offset into image - * @prop {number} dy - y offset into image - * @prop {boolean} [coordsWrap] + * @prop {number} dx - x offset into image, for a subCell of a normal tile: 0 or 1, the half of the parent tile + * @prop {number} dy - y offset into image, for a subCell of a normal tile: 0 or 1, the half of the parent tile + * @prop {boolean} [incompleteCell] - some corners cannot be projected or the cell wraps, only the subCells are drawn * @prop {Array.} [subCells] */ @@ -40,22 +42,30 @@ export function findCellOnScreen(plot, viewDim, norder, fov,centerWp, desiredNor let badCnt; let cell; let devPtCorners; + const dataCoordSys= plot.dataCoordSys; const centerDevPt= cc.getDeviceCoords(centerWp); // this function is performance sensitive, use for loops instead of map and filter if (isHiPSAitoff(plot)){ const aitoffAll= fov>200; for(let i= 0; (i2) { + const subCells= computeIncompleteTiles(cc,dataCoordSys,norder,cells[i].ipix,viewDim, {centerDevPt}); + if (subCells) retCells.push({devPtCorners, tileNumber:cells[i].ipix, dx:0, dy:0, norder,subCells, incompleteCell:true}); + } + else if (isQuadTileOnScreen(devPtCorners, viewDim)) { + const subCells= computeDeeperTiles(cc,dataCoordSys,norder,desiredNorder,cells[i].ipix); + retCells.push({devPtCorners, tileNumber:cells[i].ipix, dx:0, dy:0, norder,subCells}); } } } @@ -81,30 +97,105 @@ export function findCellOnScreen(plot, viewDim, norder, fov,centerWp, desiredNor } /** - * - * @param wc - * @param {number} norder + * Compute the drawable parts of a cell that has some corners that cannot be projected (e.g. at the edge of the sky) + * or, with checkWrap, that wraps around the edge of an aitoff projection. + * Children that fully project are kept, incomplete children are replaced by their fully projected grandchildren. + * Only parts that are on the screen are kept, unless allOnScreen is true. + * @param {CysConverter} cc * @param {CoordinateSys} dataCoordSys + * @param {number} norder - norder of the parent tile + * @param {number} npix - healpix pixel number of the parent tile + * @param {{width:number,height:number}} viewDim + * @param {Object} [options] + * @param {boolean} [options.checkWrap] - treat a child that wraps as incomplete + * @param {boolean} [options.allOnScreen] - skip the on screen check, everything is visible (aitoff full sky) + * @param {DevicePt} [options.centerDevPt] - center of the view, if defined grandchild cells are shimmed + * @return {Array.|undefined} the drawable child cells, or undefined if none + */ +function computeIncompleteTiles(cc, dataCoordSys, norder, npix, viewDim, {checkWrap=false, allOnScreen=false, centerDevPt}={}) { + const onScreen= (t) => !t.incompleteCell && (allOnScreen || isQuadTileOnScreen(t.devPtCorners, viewDim)); + const subTiles= getProgradeTiles(cc,dataCoordSys,norder,npix, {allowPartial:true, checkWrap}); + if (!subTiles) return; + subTiles.forEach( (t) => { + if (t.incompleteCell) { + const grandChildCells= (getProgradeTiles(cc,dataCoordSys,norder+1,t.tileNumber, + {allowPartial:true, checkWrap, shim:Boolean(centerDevPt), centerDevPt, viewDim}) ?? []) + .filter(onScreen); + t.subCells= grandChildCells.length>0 ? grandChildCells : undefined; + } + }); + const retSubTiles= subTiles.filter( (t) => t.incompleteCell ? t.subCells : onScreen(t)); + return retSubTiles.length>0 ? retSubTiles : undefined; +} + +/** + * Compute the child cells of a tile so it can be drawn as smaller quads when zoomed in beyond the tile norder. + * Goes at most two levels deep: one level when desiredNorder is norder+1, otherwise two (the second in each child's subCells). + * The dx/dy of each child is 0 or 1, the half of the parent tile image it comes from. * @param {CysConverter} cc - * @prop {HiPSDeviceTileData} + * @param {CoordinateSys} dataCoordSys + * @param {number} norder - norder of the parent tile + * @param {number} desiredNorder + * @param {number} npix - healpix pixel number of the parent tile + * @return {Array.|undefined} the 4 child cells, or undefined if not needed or any child cannot be projected */ -function makeWrappingCell(wc, norder, dataCoordSys, cc) { - if (norder>2) return {...wc, coordsWrap:true}; - const nside= norder+1; - const subCells= Array(4).fill(nside,0,4).map( (sc,idx) => { - const tileNumber = wc.ipix * 4 + idx; - const wpCorners= getCornersForCell(nside, tileNumber, dataCoordSys); - return { - nside, tileNumber, wpCorners, dx: 0, dy: 0, - devPtCorners: wpCorners.map( (wp) => cc.getDeviceCoords(wp)), - }; - } - ) - .filter( (sc) => !tileCoordsWrap(cc, sc.wpCorners, 10)); - return { ...wc, coordsWrap: true, subCells }; +function computeDeeperTiles(cc, dataCoordSys, norder, desiredNorder, npix) { + if (!desiredNorder) return; + if (desiredNorder<=norder) return; + const subTiles= getProgradeTiles(cc,dataCoordSys,norder,npix); + if (!subTiles) return; + if (desiredNorder===norder+1) return subTiles; + subTiles.forEach( (t) => { + t.subCells= getProgradeTiles(cc,dataCoordSys,norder+1,t.tileNumber); + }); + return subTiles; } +/** + * Make the 4 child cells (at norder+1) of a healpix pixel, with device corners and image offsets. + * @param {CysConverter} cc + * @param {CoordinateSys} dataCoordSys + * @param {number} norder - norder of the parent tile + * @param {number} npix - healpix pixel number of the parent tile + * @param {Object} [options] + * @param {boolean} [options.allowPartial] - allow for an incomplete tile set + * @param {boolean} [options.checkWrap] - a child that wraps (aitoff) gets no corners and is marked incomplete + * @param {boolean} [options.shim] - if true, fill in 1 or 2 unprojectable corners of a child using the shim functions + * @param {DevicePt} [options.centerDevPt] - center of the view, required when shim is true + * @param {{width:number,height:number}} [options.viewDim] - required when shim is true + * @return {Array.|undefined} the 4 child cells, or undefined if any child cannot be projected + * and allowPartial is false. With allowPartial, a child with unprojectable corners has incompleteCell set. + * The devPtCorners of an incomplete child only has the projectable corners, so the positions do not match the healpix corners. + */ +function getProgradeTiles(cc, dataCoordSys, norder, npix, + {allowPartial=false, checkWrap=false, shim=false, centerDevPt, viewDim}={}) { + const proNorder= norder+1; + const proNside= 2**proNorder; + const healpixCache=getHealpixCornerTool(); + const pgTiles= getProGradeTilePixels(npix) + .map( (tileNumber,idx) => { + const {wpCorners}= healpixCache.makeCornersForPix(tileNumber, proNside, dataCoordSys); + const wraps= checkWrap && tileCoordsWrap(cc, wpCorners, 10); + const devCorners= wraps ? [] : wpCorners.map( (wp) => cc.getDeviceCoords(wp)); + let devPtCorners= devCorners.filter(Boolean); + if (shim && devPtCorners.length<4 && centerDevPt && viewDim) { + if (devPtCorners.length===3) devPtCorners= shim1DevPtCorner(devCorners,centerDevPt, viewDim); + else if (devPtCorners.length===2) devPtCorners= shim2DevPtCorner(devCorners,centerDevPt, viewDim); + } + + if (!allowPartial && devPtCorners.length!==4) return; + return { + tileNumber, + norder: proNorder, + devPtCorners, + incompleteCell: devPtCorners.length!==4, + dx: imageOffsets[idx][0], + dy: imageOffsets[idx][1], + }; + }); + return pgTiles.every(Boolean) ? pgTiles : undefined; // a child is only undefined when allowPartial is false +} function shim1DevPtCorner(devPtCorners,centerDevPt, viewDim) { const {width,height}= viewDim; diff --git a/src/firefly/js/visualize/iv/HiPSRenderer.js b/src/firefly/js/visualize/iv/HiPSRenderer.js index d8390eb1a0..fd0ea60411 100644 --- a/src/firefly/js/visualize/iv/HiPSRenderer.js +++ b/src/firefly/js/visualize/iv/HiPSRenderer.js @@ -3,7 +3,6 @@ */ import {isNil} from 'lodash'; -import BrowserInfo from '../../util/BrowserInfo'; import {callWhileAwaiting} from '../../util/WebUtil'; import {NO_COLOR_TABLE} from '../rawData/ColorTable'; import {retrieveAndProcessImage} from './ImageProcessor.js'; @@ -47,6 +46,20 @@ export function makeHipsRenderer(screenRenderParams, totalCnt, isBaseImage, scre // ------------------------- private functions // ------------------------------------------------------------ + const normalCaseDrawOneCell= (tile, image, tileSize= tile.tileSize || image.width, x= tile.dx, y= tile.dy) => { + if (tile.subCells && (tile.incompleteCell || desiredNorder>norder)) { + const half= tileSize/2; + tile.subCells.forEach( (subTile) => { + normalCaseDrawOneCell(subTile,image, half, x+subTile.dx*half, y+subTile.dy*half); + }); + } + else { + if (!tile.incompleteCell) { + drawOneHiPSTile(offscreenCtx, image, tile.devPtCorners, tileSize, {x,y}, isMaxOrder, norder, desiredNorder); + } + } + }; + /** * draw a single tile async (retrieve image and draw tile) * @param src @@ -117,8 +130,7 @@ export function makeHipsRenderer(screenRenderParams, totalCnt, isBaseImage, scre } if (abortRender) return; - const tileSize= tile.tileSize || image.width; - drawOneHiPSTile(offscreenCtx, image, tile.devPtCorners, tileSize, {x:tile.dx,y:tile.dy}, isMaxOrder, norder, desiredNorder); + normalCaseDrawOneCell(tile,image); if (doRenderNow()) renderToScreen(); @@ -126,12 +138,7 @@ export function makeHipsRenderer(screenRenderParams, totalCnt, isBaseImage, scre }).catch(() => { renderedCnt++; if (abortRender) return; - if (tile.devPtCorners.filter( (t) => t).length ===4) { - drawOneHiPSTile(offscreenCtx, emptyTileCanvas, tile.devPtCorners, 512, {x:tile.dx,y:tile.dy}, isMaxOrder, norder, desiredNorder); - } - else { - console.log('********************* found one'); - } + normalCaseDrawOneCell(tile, emptyTileCanvas); addFailedImage(src); if (doRenderNow()) { renderComplete= true; @@ -145,21 +152,9 @@ export function makeHipsRenderer(screenRenderParams, totalCnt, isBaseImage, scre * draw a tile when all * @param image * @param {HiPSDeviceTileData} tile - * @param {HiPSAllSkyCacheInfo} [cachedAllSkyData] */ - const drawTileImmediate= (image, tile, cachedAllSkyData) => { - if (image) { - if (tile.coordsWrap && cachedAllSkyData) { - tile.subCells?.forEach( (cell) => { - const subImage= cachedAllSkyData.order3Array[cell.tileNumber]; - drawOneHiPSTile(offscreenCtx, subImage, cell.devPtCorners, subImage.width, {x:0,y:0}, isMaxOrder, norder, desiredNorder); - }); - } - else { - const tileSize= tile.tileSize || image.width; - drawOneHiPSTile(offscreenCtx, image, tile.devPtCorners, tileSize, {x:tile.dx,y:tile.dy}, isMaxOrder, norder, desiredNorder); - } - } + const drawTileImmediate= (image, tile) => { + if (image) normalCaseDrawOneCell(tile,image); renderedCnt++; if (renderedCnt === totalCnt) { renderComplete= true; @@ -229,7 +224,7 @@ export function makeHipsRenderer(screenRenderParams, totalCnt, isBaseImage, scre if (abortRender) return; const allSkyAry= norder===3 ? cachedAllSky.order3Array : cachedAllSky.order2Array; for(let i=0; i isImage(primePlot(pv))); + } + if (imagePv) matchImageToHips(pv, imagePv); } } } From 0674bf01a344549b59e76029adcfcfa19f59b5c2 Mon Sep 17 00:00:00 2001 From: roby Date: Fri, 25 Sep 2026 09:42:36 -0600 Subject: [PATCH 2/2] Firefly-2120: response to feedback --- .../js/visualize/iv/HiPSSingleTileRender.js | 43 ++----------------- src/firefly/js/visualize/task/ZoomTask.js | 2 +- 2 files changed, 5 insertions(+), 40 deletions(-) diff --git a/src/firefly/js/visualize/iv/HiPSSingleTileRender.js b/src/firefly/js/visualize/iv/HiPSSingleTileRender.js index 17a11ec369..f822684388 100644 --- a/src/firefly/js/visualize/iv/HiPSSingleTileRender.js +++ b/src/firefly/js/visualize/iv/HiPSSingleTileRender.js @@ -4,17 +4,6 @@ import {Matrix} from '../../externalSource/transformation-matrix-js/matrix'; - -const makeSource4Triangle= (centerPt, min, max) => { - return [ - [{x:max, y:max}, centerPt, {x:max, y:min}], // 3 > - [{x:max, y:min}, centerPt, {x:min, y:min}], // 12 ^ - [{x:min, y:max}, centerPt, {x:min, y:min}], // 9 < - [{x:max, y:max}, centerPt, {x:min, y:max}], // 6 v - ]; -}; - - /** * Compute the amount of correction based on how zoom in the display is, The more zoomed in the less correction * is needed. Too much correction make for distortion @@ -54,36 +43,12 @@ function getCorrection(tileSize, norder,desiredNorder,isMaxOrder) { * @param {number} desiredNorder */ export function drawOneHiPSTile(ctx, img, cornersAry, tileSize, offset, isMaxOrder, norder, desiredNorder) { - const triangles= norder > isMaxOrder && desiredNorder>norder ? 4 : 2; const correction= getCorrection(tileSize,norder,desiredNorder,isMaxOrder); + const triangle1= [{x:tileSize, y:tileSize}, {x:tileSize, y:0}, {x:0, y:tileSize}]; + const triangle2= [{x:tileSize, y:0}, {x:0, y:tileSize}, {x:0, y:0}]; - if (triangles===2) { - const triangle1= [{x:tileSize, y:tileSize}, {x:tileSize, y:0}, {x:0, y:tileSize}]; - const triangle2= [{x:tileSize, y:0}, {x:0, y:tileSize}, {x:0, y:0}]; - - drawTexturedTriangle(ctx, img, offset, ...triangle1, cornersAry[0], cornersAry[1], cornersAry[3], correction, true); - drawTexturedTriangle(ctx, img,offset, ...triangle2, cornersAry[1], cornersAry[3], cornersAry[2], correction, true); - } - else if (triangles===4) { - draw4Triangles(ctx, img, correction, offset, cornersAry,tileSize); - } - else if (triangles===8) { // keep this section around if we have to use it, it is not complete and not tested - //todo - will probably never do this - } -} - - -function draw4Triangles(ctx, img, correction, offset, cornersAry,tileSize) { - const mp=tileSize/2; - const cMx= cornersAry.reduce( (total,pt) => total+pt.x, 0)/cornersAry.length; - const cMy= cornersAry.reduce( (total,pt) => total+pt.y, 0)/cornersAry.length; - const cPt= {x:cMx,y:cMy}; - - const [triangle1, triangle2, triangle3, triangle4]= makeSource4Triangle({x:mp, y:mp}, 0, tileSize); - drawTexturedTriangle(ctx, img, offset, ...triangle1, cornersAry[0], cPt, cornersAry[1], correction, false); // 3 > - drawTexturedTriangle(ctx, img, offset, ...triangle2, cornersAry[1], cPt, cornersAry[2], correction, false); // 12 ^ - drawTexturedTriangle(ctx, img, offset, ...triangle3, cornersAry[3], cPt, cornersAry[2], correction, false); // 9 < - drawTexturedTriangle(ctx, img, offset, ...triangle4, cornersAry[0], cPt, cornersAry[3], correction, false); // 6 v + drawTexturedTriangle(ctx, img, offset, ...triangle1, cornersAry[0], cornersAry[1], cornersAry[3], correction, true); + drawTexturedTriangle(ctx, img,offset, ...triangle2, cornersAry[1], cornersAry[3], cornersAry[2], correction, true); } diff --git a/src/firefly/js/visualize/task/ZoomTask.js b/src/firefly/js/visualize/task/ZoomTask.js index 2a3725f403..f5413e9fd0 100644 --- a/src/firefly/js/visualize/task/ZoomTask.js +++ b/src/firefly/js/visualize/task/ZoomTask.js @@ -132,7 +132,7 @@ function alignWCS(getState, pv) { } else if (isHiPS(primePlot(pv))) { let imagePv= getPlotViewById(visRoot, visRoot.mpwWcsPrimId); - if (!isImage(primePlot(pv))) { + if (!isImage(primePlot(imagePv))) { imagePv= visRoot.plotViewAry.find( (pv) => isImage(primePlot(pv))); } if (imagePv) matchImageToHips(pv, imagePv);