diff --git a/src/firefly/html/demo/ffapi-2images.html b/src/firefly/html/demo/ffapi-2images.html index c9e34b88db..b6175225ed 100644 --- a/src/firefly/html/demo/ffapi-2images.html +++ b/src/firefly/html/demo/ffapi-2images.html @@ -237,6 +237,9 @@

Firefly - new API demo

}; firefly.showImage('image2_div', req2); + firefly.action.dispatchCreateRegionLayer('region2', 'Region Layer 2', null, ['image; box 200 200 72 72 0 # color=red'], ['image1', 'image2']); + + } } diff --git a/src/firefly/html/demo/ffapi-highlevel-test.html b/src/firefly/html/demo/ffapi-highlevel-test.html index 6244c18fb7..b47937a115 100644 --- a/src/firefly/html/demo/ffapi-highlevel-test.html +++ b/src/firefly/html/demo/ffapi-highlevel-test.html @@ -231,9 +231,12 @@ firefly.addXYPlot({QUERY_ID: 'oldSelectable'}, 'oldXyPlot1'); //-----< old xyplot api ------// - var regionAry = [ + window.regionAry = [ + /* 'global color=green dashlist=8 3 width=1 font="helvetica 10 normal normal" select=1 highlite=1 dash=0 fixed=0 edit=1 move=1 delete=1 include=1 rotate=0 source=1', 'J2000;point 202.41 47.262 # color=pink text="pt circle 1" point=circle', + 'box (100p, 70p, 20p, 20p, 0) #color=red text={Physical coordinate - 1}', + 'box (100i, 70i, 30i, 30i, 0) #color=orange text={Image coordinate -2}', 'line(202.414796 47.281999 202.423758 47.247072) # color=orange width=10 select=0 text={line 2}', 'text 30p 40p # color=pink text={text test 3} edit=0 highlite=0 font="BRAGGADOCIO 10 normal roman"', 'text 202.437691 47.234228{more text testing 4} # color=purple move=0', @@ -252,7 +255,38 @@ 'j2000;box(47.247072i, 180.445347i, 50p, 20p, 0) # color=blue width=6 text="box 12-3"', 'physical;-box point 12 12 # text="pt box 13"', 'j2000;polygon(202.564796, 47.281999,202.553758, 47.247072, 202.445347, 47.244296, 202.479687, 47.264027, 202.492153, 47.290841) # color=blue text="polygon 14" offsety=10 width=10 font="helvetica 16 bold"', - 'point 202.45 47.2879 # color=cyan text="pt arrow 15" delete=0 point=arrow 20' + 'point 202.45 47.2879 # color=cyan text="pt arrow 15" delete=0 point=arrow 20', + 'IMAGE;box (160, 70, 20, 20, 0) #color=red text={IMAGE test - 1}', + 'PHYSICAL;box (160, 70, 30, 30, 0) #color=orange text={PHYSICAL test -2}' + */ + 'box (240, 220, 20, 20, 0) #color=red text={ ph1}', + 'box (240i, 220i, 60i, 60i, 0) #color=orange text={ph2}', + 'J2000;point 202.41 47.262 # color=pink text="pt circle 1" point=circle', + 'IMAGE;box (360, 220, 20, 20, 0) #color=red text={ im1}', + 'PHYSICAL;box (360, 220, 60, 60, 0) #color=orange text={ph3}' + ]; + + window.regionAry2 = [ + 'J2000', + 'boxcircle point 202.45 47.262 # color=red text="pt boxcircle 6" delete=0', + 'physical;circle 80 140 20 # color=red offsetx=25 offsety=2 width=5 edit=0 text="circle 7"', + 'annulus 13h30m16.41s +47d14m43.9s 30p 40p 50p # color=green text="hello" include=0 text="annulus 8"', + 'physical;point 200 140 # color=yellow point=cross 20 text="pt cross 9" offsetx=10', + 'physical;point 13h29m52.73s, +47d11m40.9s # color=purple point=diamond 15 text="pt diamond 10"', + '#circle(202.55556, 47.188286 , 20p) # color=blue text="text 11"', + 'box(202.55556, 47.188286 ,20p,40p, 30p, 50p, 0) # color=red width=5 text="boxann 11"', + 'box(202.52556,47.226286,0.0240,0.006,0) # color=green width=5 text="box 11-2"', + 'image;box(100, 150, 50p, 20p, 2r) # color=magenta width=6 text="slanted box 12"', + 'image;box(190.564796, 47.281999, 50p, 20p, 0) # color=red width=6 offsety=-15 text="box 12-1"', + 'j2000;box(47.247072i, 180.445347i, 50p, 20p, 0) # color=blue width=6 text="box 12-3"', + 'physical;-box point 12 12 # text="pt box 13"', + 'j2000;polygon(202.564796, 47.281999,202.553758, 47.247072, 202.445347, 47.244296, 202.479687, 47.264027, 202.492153, 47.290841) # color=blue text="polygon 14" offsety=10 width=10 font="helvetica 16 bold"', + 'point 202.45 47.2879 # color=cyan text="pt arrow 15" delete=0 point=arrow 20', + ]; + + window.regionWithError = [ + 'image; box 280 200 72 72 # color=blue text={wrong syntax}', + 'image; box 280 200 72 72 0 # color=cyan text={right syntax}' ]; var moreRegionAry = [ @@ -264,7 +298,7 @@ window.regions = []; window.regionId = window.regions.length; - document.getElementById('regionLayerContent').value = regionAry.join('\n'); + document.getElementById('regionLayerContent').value = window.regionAry.join('\n'); document.getElementById('moreRegionContent').value = moreRegionAry.join('\n'); //document.getElementById('createRegionId').placeholder = "Region_Plot_" + (window.regionId+1); updateRegionLayerList(); @@ -279,6 +313,14 @@ document.getElementById('createRegionId').value = layerId; } + if (window.regionId === 3) { + document.getElementById('regionLayerContent').value = window.regionWithError.join('\n'); + } else if (window.regionId > 1) { + document.getElementById('regionLayerContent').value = window.regionAry2.join('\n'); + } else { + document.getElementById('regionLayerContent').value = window.regionAry.join('\n'); + } + var regionAry = document.getElementById('regionLayerContent').value.split('\n').filter(function(r) { return (r.length !== 0);}); window.regions.push(layerId); updateRegionLayerList(); @@ -355,7 +397,7 @@ selectBox.getElementsByTagName('option')[0].selected = 'selected'; firefly.action.dispatchRemoveRegionEntry(selectedLayerId, removeRegions); firefly.action.dispatchRemoveRegionEntry(selectedLayerId, removeRegions, window.ffViewer.dispatch); - } + }; plotRemote= function() { firefly.getViewer().showImage({plotId: 'xxq', diff --git a/src/firefly/js/drawingLayers/RegionPlot.js b/src/firefly/js/drawingLayers/RegionPlot.js index c14d40f01c..d9477044f5 100644 --- a/src/firefly/js/drawingLayers/RegionPlot.js +++ b/src/firefly/js/drawingLayers/RegionPlot.js @@ -14,7 +14,7 @@ import {MouseState} from '../visualize/VisMouseSync.js'; import DrawOp from '../visualize/draw/DrawOp.js'; import DrawLayerCntrl, {dispatchModifyCustomField, dispatchAddRegionEntry, - dispatchRemoveRegionEntry} from '../visualize/DrawLayerCntlr.js'; + dispatchRemoveRegionEntry, dlRoot} from '../visualize/DrawLayerCntlr.js'; import {get, isEmpty} from 'lodash'; @@ -125,7 +125,17 @@ function highlightChange(mouseStatePayload) { const sId = window.setInterval( () => { if (done) { window.clearInterval(sId); - dispatchModifyCustomField(TYPE_ID, {highlightedRegion: closestObj}, false); + + // set the highlight region on current drawLayer, + // unset the highlight on other drawLayer if a highlight is found for current layer + + dlRoot().drawLayerAry.forEach( (dl) => { + if (dl.drawLayerId === drawLayer.drawLayerId) { + dispatchModifyCustomField(dl.drawLayerId, {highlightedRegion: closestObj}, plotId, false); + } else if (closestObj) { + dispatchModifyCustomField(dl.drawLayerId, {highlightedRegion: null}, plotId, false); + } + }); } for (let i = 0; i < maxChunk; i++ ) { @@ -157,30 +167,27 @@ function highlightChange(mouseStatePayload) { * @returns {*} */ function getLayerChanges(drawLayer, action) { - const {changes, regionId, regionChanges } = action.payload; + const {changes, regionId, regionChanges, drawLayerId } = action.payload; + + if (drawLayerId && drawLayerId !== drawLayer.drawLayerId) return null; var dd = Object.assign({}, drawLayer.drawData); switch (action.type) { case DrawLayerCntlr.MODIFY_CUSTOM_FIELD: - /* - if (changes && changes.regions) { // this should not happen - dd[DataTypes.HIGHLIGHT_DATA] = null; - dd[DataTypes.DATA] = null; - if (drawLayer.highlightedRegion) drawLayer.highlightedRegion = null; - } else */ - if (changes && changes.highlightedRegion) { - dd[DataTypes.HIGHLIGHT_DATA] = null; - if (drawLayer.highlightedRegion) drawLayer.highlightedRegion.highlight = 0; - changes.highlightedRegion.highlight = 1; - } else if (changes) { - dd[DataTypes.HIGHLIGHT_DATA] = null; - if (drawLayer.highlightedRegion) { - drawLayer.highlightedRegion.highlight = 0; // un-highlight the last one - drawLayer.highlightedRegion = null; - } - } - - return Object.assign({}, changes, {drawData: dd}); + if (changes) { + dd[DataTypes.HIGHLIGHT_DATA] = null; + if (!changes.highlightedRegion) { + if (drawLayer.highlightedRegion) { + drawLayer.highlightedRegion.highlight = 0; // un-highlight the last selected region + drawLayer.highlightedRegion = null; + } + } else { + if (drawLayer.highlightedRegion) drawLayer.highlightedRegion.highlight = 0; + changes.highlightedRegion.highlight = 1; + + } + } + return Object.assign({}, changes, {drawData: dd}); case DrawLayerCntrl.REGION_ADD_ENTRY: if (regionId === drawLayer.drawLayerId && regionChanges) { dd[DataTypes.DATA] = addRegionsToData(drawLayer, dd[DataTypes.DATA], regionChanges); diff --git a/src/firefly/js/visualize/draw/PointDataObj.js b/src/firefly/js/visualize/draw/PointDataObj.js index 22fbe0d0d0..a29c13babc 100644 --- a/src/firefly/js/visualize/draw/PointDataObj.js +++ b/src/firefly/js/visualize/draw/PointDataObj.js @@ -443,6 +443,7 @@ export function makeHighlightPointDataObj(drawObj, cc) { 0.0, ShapeDataObj.UnitType.ARCSEC, false); makeShapeHighlightRenderOptions( rectObj ); + rectObj.isAHighlight = { from: drawObj, plotImageId: cc.plotImageId}; return rectObj; } diff --git a/src/firefly/js/visualize/draw/ShapeDataObj.js b/src/firefly/js/visualize/draw/ShapeDataObj.js index f733d521f5..48dee18fa7 100644 --- a/src/firefly/js/visualize/draw/ShapeDataObj.js +++ b/src/firefly/js/visualize/draw/ShapeDataObj.js @@ -12,6 +12,7 @@ import {TextLocation, Style, DEFAULT_FONT_SIZE} from './DrawingDef.js'; import Point, {makeScreenPt, makeViewPortPt, makeOffsetPt, makeWorldPt, makeImagePt} from '../Point.js'; import {toRegion} from './ShapeToRegion.js'; import {getDrawobjArea, isScreenPtInRegion, makeHighlightShapeDataObj} from './ShapeHighlight.js'; +import {makeHighlightPointDataObj, POINT_DATA_OBJ} from './PointDataObj.js'; import CsysConverter from '../CsysConverter.js'; import {has, isNil, get, set} from 'lodash'; @@ -233,6 +234,14 @@ var draw= { }, draw(drawObj,ctx,drawTextAry,plot,def,vpPtM,onlyAddToPath) { + if (has(drawObj, 'isAHighlight') && drawObj.isAHighlight.plotImageId !== plot.plotImageId) { + var fromObj = get(drawObj.isAHighlight, 'from'); + + if (fromObj) { + drawObj = (fromObj.type === POINT_DATA_OBJ) ? makeHighlightPointDataObj(fromObj, plot): + makeHighlightShapeDataObj(fromObj, plot, drawObj.isAHighlight.def); + } + } var drawParams= makeDrawParams(drawObj,def); drawShape(drawObj,ctx,drawTextAry,plot,drawParams,onlyAddToPath); }, diff --git a/src/firefly/js/visualize/draw/ShapeHighlight.js b/src/firefly/js/visualize/draw/ShapeHighlight.js index da908dc6c1..a8d0762670 100644 --- a/src/firefly/js/visualize/draw/ShapeHighlight.js +++ b/src/firefly/js/visualize/draw/ShapeHighlight.js @@ -663,6 +663,8 @@ export function makeHighlightShapeDataObj(drawObj, cc, def = {}) { var rectObj = ShapeDataObj.makeRectangleByCenter(wcenter, w, h, ShapeDataObj.UnitType.PIXEL, 0.0, ShapeDataObj.UnitType.ARCSEC, false); makeShapeHighlightRenderOptions( rectObj ); + + rectObj.isAHighlight = { from: drawObj, plotImageId: cc.plotImageId, def}; return rectObj; } diff --git a/src/firefly/js/visualize/region/RegionDrawer.js b/src/firefly/js/visualize/region/RegionDrawer.js index 41326826dc..9b7d8db189 100644 --- a/src/firefly/js/visualize/region/RegionDrawer.js +++ b/src/firefly/js/visualize/region/RegionDrawer.js @@ -337,9 +337,10 @@ function drawRegionAnnulus(regionObj) { * @param options region properties * @param propChkAry property cheeck list * @param a rotation angle + * @param isOnWorld * @returns {*} */ -function drawOneBox(w, h, a, wp, options, propChkAry) { +function drawOneBox(w, h, a, wp, options, propChkAry, isOnWorld) { var unit = regionUnitToDrawObj(w.unit); var angleUnit = regionUnitToDrawObj(a.unit); var width, height, angle; @@ -368,7 +369,7 @@ function drawOneBox(w, h, a, wp, options, propChkAry) { angleUnit = ShapeDataObj.UnitType.ARCSEC; } - var dObj = ShapeDataObj.makeRectangleByCenter(wp, width, height, unit, angle, angleUnit, wp.type === Point.W_PT); + var dObj = ShapeDataObj.makeRectangleByCenter(wp, width, height, unit, angle, angleUnit, isOnWorld); updateDrawobjProp(propChkAry, options, dObj); return dObj; @@ -387,7 +388,7 @@ function drawRegionBox(regionObj) { regionObj.angle, regionObj.wpAry[0], regionObj.options, - allProps); + allProps, regionObj.isOnWorld); dObj.textLoc = DEFAULT_TEXTLOC[RegionType.box.key]; return [dObj]; @@ -406,7 +407,7 @@ function drawRegionBoxAnnulus(regionObj) { regionObj.angle, regionObj.wpAry[0], regionObj.options, - commonProps); + commonProps, regionObj.isOnWorld); var boxannulusObj = ShapeDataObj.makeBoxAnnulus(regionObj.wpAry[0], dimAry(regionObj.dimensionAry, firstObj.unitType), firstObj.unitType, @@ -419,7 +420,7 @@ function drawRegionBoxAnnulus(regionObj) { boxannulusObj = Object.assign(boxannulusObj, pick(firstObj, commonProps)); var moreObj = regionObj.dimensionAry.reverse().slice(1).map((d) => { - var nextObj = drawOneBox(d.width, d.height, regionObj.angle, regionObj.wpAry[0], regionObj.options, []); + var nextObj = drawOneBox(d.width, d.height, regionObj.angle, regionObj.wpAry[0], regionObj.options, [], regionObj.isOnWorld); return Object.assign(nextObj, pick(firstObj, commonProps)); }); @@ -488,9 +489,10 @@ function drawRegionPolygon(regionObj) { * @param options region properties * @param propChkAry property cheeck list * @param a rotation angle + * @param isOnWorld * @returns {*} */ -function drawOneEllipse(r1, r2, a, wp, options, propChkAry) { +function drawOneEllipse(r1, r2, a, wp, options, propChkAry, isOnWorld) { var unit = regionUnitToDrawObj(r1.unit); var angleUnit = regionUnitToDrawObj(a.unit); var radius1, radius2, angle; @@ -508,7 +510,6 @@ function drawOneEllipse(r1, r2, a, wp, options, propChkAry) { } else { radius1 = r1.value; radius2 = r2.value; -// angle = 0.0; } // DS9 angle is counterclockwise, canvas angle is clockwise @@ -519,7 +520,7 @@ function drawOneEllipse(r1, r2, a, wp, options, propChkAry) { angleUnit = ShapeDataObj.UnitType.ARCSEC; } - var dObj = ShapeDataObj.makeEllipse(wp, radius1, radius2, unit, angle, angleUnit, wp.type === Point.W_PT); + var dObj = ShapeDataObj.makeEllipse(wp, radius1, radius2, unit, angle, angleUnit, isOnWorld); updateDrawobjProp(propChkAry, options, dObj); return dObj; @@ -538,7 +539,7 @@ function drawRegionEllipse(regionObj) { regionObj.angle, regionObj.wpAry[0], regionObj.options, - allProps); + allProps, regionObj.isOnWorld); dObj.textLoc = DEFAULT_TEXTLOC[RegionType.ellipse.key]; return [dObj]; @@ -556,7 +557,7 @@ function drawRegionEllipseAnnulus(regionObj) { regionObj.angle, regionObj.wpAry[0], regionObj.options, - commonProps); + commonProps, regionObj.isOnWorld); var ellipseannObj = ShapeDataObj.makeEllipseAnnulus(regionObj.wpAry[0], dimAry(regionObj.dimensionAry, firstObj.unitType), firstObj.unitType, @@ -569,7 +570,7 @@ function drawRegionEllipseAnnulus(regionObj) { ellipseannObj = Object.assign(ellipseannObj, pick(firstObj, commonProps)); var moreObj = regionObj.dimensionAry.reverse().slice(1).map((d) => { - var nextObj = drawOneEllipse(d.width, d.height, regionObj.angle, regionObj.wpAry[0], regionObj.options, []); + var nextObj = drawOneEllipse(d.width, d.height, regionObj.angle, regionObj.wpAry[0], regionObj.options, [], regionObj.isOnWorld); return Object.assign(nextObj, pick(firstObj, commonProps)); }); diff --git a/src/firefly/js/visualize/region/RegionFactory.js b/src/firefly/js/visualize/region/RegionFactory.js index be079585bf..3bda7b91c1 100644 --- a/src/firefly/js/visualize/region/RegionFactory.js +++ b/src/firefly/js/visualize/region/RegionFactory.js @@ -11,11 +11,12 @@ import { RegionType, RegionCsys, RegionValueUnit, regionPropsList, import validator from 'validator'; import CoordUtil from '../CoordUtil.js'; import {CoordinateSys} from '../CoordSys.js'; -import {makeWorldPt, makeImagePt, makeScreenPt} from '../Point.js'; +import {makeWorldPt, makeImagePt} from '../Point.js'; import {convertAngle} from '../VisUtil.js'; import CsysConverter from '../CsysConverter.js'; import {primePlot} from '../PlotViewUtil.js'; import {visRoot } from '../ImagePlotCntlr.js'; +import {logError} from '../../util/WebUtil.js' import {set, unset, has, get, isEmpty} from 'lodash'; import Enum from 'enum'; @@ -31,6 +32,16 @@ var RegionParseError = { NotImplemented: 'region type is not yet implemented' }; +function outputError(rg, rgStr) { + if (rg.type === RegionType.message) { + logError(rg.message); + } else if (!rg.options) { + logError(`[invalid region: no options created]: '${rgStr}'`); + } else if (rg.type === RegionType.undefined ) { + logError(`[invalid region: undefined region + type] '${rgStr}'`); + } +} export class RegionFactory { @@ -45,6 +56,7 @@ export class RegionFactory { if (rg) { // skip comment line and no good line prev.push(rg); + outputError(rg, region); } return prev; }, []) : null; @@ -80,6 +92,7 @@ export class RegionFactory { } else { prev.push(rg); } + outputError(rg, region); } return prev; }, []) : null; @@ -146,9 +159,9 @@ export class RegionFactory { regionCoord = tmpAry[0].trim(); tmpAry = tmpAry[1].split('#'); } else { - // default coordinate is J2000 in case not specified + // default coordinate is PHYSICAL in case not specified regionCoord = globalOptions && has(globalOptions, regionPropsList.COORD) ? - globalOptions[regionPropsList.COORD] : 'J2000'; + globalOptions[regionPropsList.COORD] : 'PHYSICAL'; tmpAry = tmpAry[0].split('#'); } @@ -180,7 +193,6 @@ export class RegionFactory { return makeRegionMsg(`[${RegionParseError.InvalidCoord}] ${rgMsg}`); } - // check region description syntax and region type // [ RegionType, wp.x, wp.y, ...], at least 3 items @@ -363,7 +375,7 @@ export class RegionFactory { if (params.length < 2) break; if (wp1 = this.parseXY(regionCsys, params[n], params[++n])) { - region = makeRegionText(wp1); + region = makeRegionText(wp1.pt); } if (params.length >= 3) { region.options = makeRegionOptions({text: params[2]}); @@ -374,7 +386,7 @@ export class RegionFactory { if (params.length < 2) break; if (wp1 = this.parseXY(regionCsys, params[n], params[++n])) { - region = makeRegionPoint(wp1); + region = makeRegionPoint(wp1.pt); } if (pointType) { region.options = makeRegionOptions({pointType}); @@ -395,8 +407,8 @@ export class RegionFactory { // width & height while (params.length > (n + 3)) { - w = this.convertToRegionValue(params[++n], regionCsys); - h = this.convertToRegionValue(params[++n], regionCsys); + w = this.convertToRegionValueForDim(params[++n], regionCsys); + h = this.convertToRegionValueForDim(params[++n], regionCsys); if (!h || !w) { isAnnulus = -1; // width or height error break; @@ -414,9 +426,9 @@ export class RegionFactory { } if (isAnnulus) { // boxannulus - region = makeRegionBoxAnnulus(wp1, dimAry, angle); + region = makeRegionBoxAnnulus(wp1.pt, dimAry, angle); } else { - region = makeRegionBox(wp1, dimAry[0], angle); + region = makeRegionBox(wp1.pt, dimAry[0], angle); } break; @@ -432,7 +444,7 @@ export class RegionFactory { radAry = []; while (params.length > (n + 1)) { - r = this.convertToRegionValue(params[++n], regionCsys); + r = this.convertToRegionValueForDim(params[++n], regionCsys); if (!r) { radAry = []; break; @@ -441,7 +453,7 @@ export class RegionFactory { } } if (radAry.length >= 2) { - region = makeRegionAnnulus(wp1, radAry); + region = makeRegionAnnulus(wp1.pt, radAry); } break; @@ -454,11 +466,11 @@ export class RegionFactory { break; } - if (!(r = this.convertToRegionValue(params[++n], regionCsys))) { + if (!(r = this.convertToRegionValueForDim(params[++n], regionCsys))) { break; } - region = makeRegionCircle(wp1, r); + region = makeRegionCircle(wp1.pt, r); break; case RegionType.ellipse: // 4 params x, y, r1, r2, r3, r4,.. angle @@ -474,8 +486,8 @@ export class RegionFactory { dimAry = []; while (params.length > (n + 3)) { - const r1 = this.convertToRegionValue(params[++n], regionCsys); - const r2 = this.convertToRegionValue(params[++n], regionCsys); + const r1 = this.convertToRegionValueForDim(params[++n], regionCsys); + const r2 = this.convertToRegionValueForDim(params[++n], regionCsys); if (!r1 || !r2) { isAnnulus = -1; // width or height error break; @@ -494,9 +506,9 @@ export class RegionFactory { } if (isAnnulus) { - region = makeRegionEllipseAnnulus(wp1, dimAry, angle); + region = makeRegionEllipseAnnulus(wp1.pt, dimAry, angle); } else { - region = makeRegionEllipse(wp1, dimAry[0], angle); + region = makeRegionEllipse(wp1.pt, dimAry[0], angle); } break; @@ -511,7 +523,7 @@ export class RegionFactory { if (!(wp2 = this.parseXY(regionCsys, params[++n], params[++n]))) { break; } - region = makeRegionLine(wp1, wp2); + region = makeRegionLine(wp1.pt, wp2.pt); break; case RegionType.polygon: // at least 6 params x1, y1, x2, y2, x3, y3, ... @@ -527,7 +539,7 @@ export class RegionFactory { wpAry = []; break; } - wpAry.push(wp1); + wpAry.push(wp1.pt); n++; } if (wpAry.length >= 3) { @@ -538,6 +550,9 @@ export class RegionFactory { region = null; } + if (region) { + region.isOnWorld = wp1.isOnWorld; + } return region; } @@ -551,31 +566,24 @@ export class RegionFactory { */ parseXY(coordSys, xStr, yStr) { - var rgValX = xStr && this.convertToRegionValue(xStr, coordSys, CoordType.lon); - var rgValY = yStr && this.convertToRegionValue(yStr, coordSys, CoordType.lat); - + var {rgValX, rgValY} = xStr && yStr && this.convertToRegionValueForPt(xStr, yStr, coordSys); if (!rgValX || !rgValY || rgValX.unit !== rgValY.unit) { return null; } - var plotId = get(visRoot(), 'activePlotId'); - var plot = primePlot(visRoot(),plotId); - var cc = CsysConverter.make(plot); - // the coordinate values are refactored based on the coordinate system it works on. - return this.refactorRegionValueUnit( rgValX, rgValY, cc, coordSys); + return this.refactorRegionValueUnit( rgValX, rgValY, coordSys); } /** * refactor the region coordinate value based on the coordinate system the region is defined at * @param rvX * @param rvY - * @param cc * @param coordsys * @returns {*} */ - refactorRegionValueUnit(rvX, rvY, cc, coordsys) { + refactorRegionValueUnit(rvX, rvY, coordsys) { var isWorldUnit = (c) => ( (c !== RegionCsys.PHYSICAL) && (c !== RegionCsys.UNDEFINED) && @@ -588,14 +596,13 @@ export class RegionFactory { var makePt = (vx, vy, cs) => { if (vx.unit === RegionValueUnit.IMAGE_PIXEL) { return makeImagePt(vx.value, vy.value); - } else if (vx.unit === RegionValueUnit.SCREEN_PIXEL) { - return makeScreenPt(vx.value, vy.value); } else { return makeWorldPt(vx.value, vy.value, this.parse_coordinate(cs)); } }; - var pt; + return {pt: makePt(rvX, rvY, coordsys), isOnWorld: isWorldUnit(coordsys)}; + /* if (isWorldUnit(coordsys)) { pt = cc.getWorldCoords(makePt(rvX, rvY, coordsys)); } else if (coordsys === RegionCsys.IMAGE ) { @@ -606,6 +613,7 @@ export class RegionFactory { pt = null; } return pt; + */ } @@ -656,6 +664,7 @@ export class RegionFactory { var unit_char = vstr.charAt(vstr.length-1); var unit = RegionValueUnit.CONTEXT; var nstr; + var isTransformationChecked = false; if (!validator.isInt(unit_char) && (unit_char !== 's')) { switch(unit_char) { @@ -672,13 +681,13 @@ export class RegionFactory { unit = RegionValueUnit.RADIAN; break; case 'p': - unit = RegionValueUnit.SCREEN_PIXEL; + unit = RegionValueUnit.IMAGE_PIXEL; // treat 'p' same as 'i' (more detail transformation will be + // further investigated) + isTransformationChecked = true; break; case 'i': unit = RegionValueUnit.IMAGE_PIXEL; break; - case 's': - default: unit = RegionValueUnit.CONTEXT; } @@ -689,8 +698,11 @@ export class RegionFactory { // check if the string is a valid float number (including integer) if (!validator.isFloat(nstr)) { - var ret = this.parseCoordinates(nstr, coordSys, vType); + var ret; + if (vType) { + ret = this.parseCoordinates(nstr, coordSys, vType); + } if (ret) { nstr = ret.toString(); unit = RegionValueUnit.DEGREE; @@ -700,8 +712,7 @@ export class RegionFactory { } var val = parseFloat(nstr); - - return {unit, val}; + return {unit, val, isTransformationChecked}; } // coordinate: image or pixel coordinate will convert sexagesimal to be in J2000 first (in degree) @@ -741,39 +752,103 @@ export class RegionFactory { return RegionValue(val, unit); } - // vType: lon or lat + /** + * convert value of position based on the relevant unit + * @param xStr + * @param yStr + * @param coordSys + * @returns {Array} + */ + convertToRegionValueForPt(xStr, yStr, coordSys) { + var {unit: xUnit, val: xVal, isTransformationChecked} = this.textToValueAndUnit(xStr, coordSys, CoordType.lon); + var {unit: yUnit, val: yVal} = this.textToValueAndUnit(yStr, coordSys, CoordType.lat); + + if (xUnit !== yUnit) { + return null; + } + + var unit = xUnit; + + // keep the unit as origianlly indicated if there is + if (unit === RegionValueUnit.CONTEXT) { + if (coordSys === RegionCsys.IMAGE) { + unit = RegionValueUnit.IMAGE_PIXEL; + } else if (coordSys === RegionCsys.PHYSICAL) { + unit = RegionValueUnit.IMAGE_PIXEL; + isTransformationChecked = true; + } else { + unit = RegionValueUnit.DEGREE; + } + } else if (unit === RegionValueUnit.ARCMIN || + unit === RegionValueUnit.ARCSEC || + unit === RegionValueUnit.RADIAN) { + xVal = convertAngle(unit.key, 'degree', xVal); + yVal = convertAngle(unit.key, 'degree', yVal); + unit = RegionValueUnit.DEGREE; + } else if (!unit) { + return null; + } + + if (isTransformationChecked) { + var pt = this.transformPhytoImage(xVal, yVal); + + xVal = pt.imgX; + yVal = pt.imgY; + } + + return { rgValX: RegionValue(xVal, unit), rgValY: RegionValue(yVal, unit)}; + } + /** - * convert value of position and dimension based on the relevant unit - * @param vstr + * convert value of dimension based on the relevant unit + * @param vStr * @param coordSys - * @param vType - * @returns {null} + * @returns RegionValue */ - convertToRegionValue(vstr, coordSys, vType) { - var {unit, val} = this.textToValueAndUnit(vstr, coordSys, vType); + convertToRegionValueForDim(vStr, coordSys) { + var {unit, val, isTransformationChecked} = this.textToValueAndUnit(vStr, coordSys); // keep the unit as origianlly indicated if there is if (unit === RegionValueUnit.CONTEXT) { if (coordSys === RegionCsys.IMAGE) { unit = RegionValueUnit.IMAGE_PIXEL; } else if (coordSys === RegionCsys.PHYSICAL) { - unit = RegionValueUnit.SCREEN_PIXEL; + unit = RegionValueUnit.IMAGE_PIXEL; + isTransformationChecked = true; } else { unit = RegionValueUnit.DEGREE; } } else if (unit === RegionValueUnit.ARCMIN || - unit === RegionValueUnit.ARCSEC || - unit === RegionValueUnit.RADIAN) { + unit === RegionValueUnit.ARCSEC || + unit === RegionValueUnit.RADIAN) { val = convertAngle(unit.key, 'degree', val); unit = RegionValueUnit.DEGREE; } else if (!unit) { return null; } + if (isTransformationChecked) { + var pt = this.transformPhytoImage(val, 0.0, true); + + val = pt.imgX; + } return RegionValue(val, unit); } + transformPhytoImage(x, y, forDimension = false) { + var [LTM1_1, LTM1_2, LTM2_1, LTM2_2] = [1, 0, 0, 1]; + var [LTV1, LTV2] = [0, 0]; + + var img_x = LTM1_1 * x + LTM1_2 * y; + var img_y = LTM2_1 * x + LTM2_2 * y; + + if (forDimension) { + return {imgX: img_x, imgY: img_y}; + } else { + return {imgX : img_x + LTV1, imgY: img_y + LTV2}; + } + } /** * parse the region options diff --git a/src/firefly/test/edu/caltech/ipac/visualize/test5.reg b/src/firefly/test/edu/caltech/ipac/visualize/test5.reg new file mode 100644 index 0000000000..bfceea25fd --- /dev/null +++ b/src/firefly/test/edu/caltech/ipac/visualize/test5.reg @@ -0,0 +1,21 @@ +J2000 +point 202.58 47.262 # color=pink text="pt circle 1" point=circle +line(202.414796 47.281999 202.423758 47.247072) # color=orange width=10 select=1 text='line 2' +text 30p 40p # color=pink text={text test 3} edit=0 highlite=0 font="BRAGGADOCIO 10 normal roman" +text 202.437691 47.234228{more text testing 4} # color=purple move=0 +point 202.43 47.270 # point=x 15 color=green text="pt x 5" rotate=0 +point 202.45 47.262 # color=red text="pt boxcircle 6" delete=1 point=boxcircle 10 +physical;circle 80 140 20 # color=red offsetx=25 offsety=2 width=5 edit=0 text="circle 7" +annulus 13h30m16.41s +47d14m43.9s 20p 30p 40p # color=green text="hello" include=0 text="annulus 8" +physical;point 180 140 # color=yellow point=cross 20 text="pt cross 9" offsetx=10 +physical;point 13h29m52.73s, +47d11m40.9s # color=purple point=diamond 15 text="pt diamond 10" +#circle(202.55556, 47.188286 , 20p) # color=blue text="text 11" +physical;box(186.55556, 47.188286 ,20p,40p, 30p, 50p, 0) # color=red width=5 text="boxann 11" +physical;box(186.52556,47.226286,0.0240,0.006,0) # color=green width=5 text="box 11-2" +image;box(100, 150, 50p, 20p, 2r) # color=magenta width=6 text="slanted box 12" +image;box(190.564796, 47.281999, 50p, 20p, 0) # color=red width=6 offsety=-15 text="box 12-1" +j2000;box(47.247072i, 180.445347i, 50p, 20p, 0) # color=blue width=6 text="box 12-3" +physical;-box point 12 12 # text="pt box 13" +J2000;polygon(202.564796, 47.281999,202.553758, 47.247072, 202.445347, 47.244296, 202.479687, 47.264027, 202.492153, 47.290841) # color=blue text="polygon 14" width=1 font="helvetica 16 bold" +point 202.45 47.2879 # color=cyan text="pt arrow 15" delete=1 point=arrow 20 +