It looks like you have already done the hard part: converting the GPS coordinates into a relative bearing (and distance).
If the center of your 360° image points to 130° from North (assuming clockwise around the compass) and the bearing from the camera location and the hotspot is 170° from North, then it would appear that the hotspot is at 40° on your image, relative to the center of the image. And, since the image contains 360° and 1024px horizontally, then it would seem that the hotspot is located at 1024px / 360° * 40° = 114 px from the center of the image.
And since the camera and the hotspot are both at the same altitude, the relative pitch is zero.
Putting this together, you get the coordinates: 512 + 114, 256 + 0 = coordinates: 626, 256.
If the altitude of the hotspot were not the same as the camera, then you'd have to compute a pitch using some simple trig.:
First let us assume that ground distance
= the distance at ground level between the camera location and the hotspot location. This will be the same regardless of the altitude of each.
So, your pitch would be: atan [ (hotspot altitude - camera altitude) / ground distance ].
For example, if you had a ground distance of 100m and the hotspot were at 10.75m with the camera still at 2m altitude, then you'd compute your pitch as:
pitch = atan [ (10.75m - 2m) / 100m ] = atan ( 8.75m / 100m ) = atan (0.0875) = 5°
To plot this on your panorama: 512px / 180° * 5° = 14px higher than the middle. Since the middle is at 256px and the top-left of the image is 0,0, then we'd subtract 14px from 256 to arrive at 242px.
Putting this all together into Javascript as you requested:
// We'll use degrees, but this would be simpler if
// everything were computed in radians, since that
// is how the Math methods work.
function getRelativePitch(cameraAlt, hsAlt, groundDistance)
{
var degPerRad = 180 / Math.PI;
if (groundDistance == 0) { return 0.0; } // fringe case
var rad = Math.atan( ( hsAlt - cameraAlt) / groundDistance );
// Convert to degress
return rad * degPerRad;
}
// Pretty simply this one.
function getRelativeHeading(cameraHeading, hsHeading)
{
return hsHeading - cameraHeading;
}
var cameraHeading = 130; // degrees
var hotspotHeading = 170; // degrees
var cameraAltitude = 2; // meters
var hotspotAltitude = 10.75; // meters
var groundDistance = 100; // meters
var panoWidth = 1024; // pixels
var panoHeight = 512; // pixels
var panoRangeX = 360; // degrees
var panoRangeY = 180; // degrees
var relativeHeading = getRelativeHeading(cameraHeading, hotspotHeading);
var relativePitch = getRelativePitch(cameraAltitude, hotspotAltitude, groundDistance);
// Now convert to pixels
var hotspotX = Math.round( panoWidth / 2 + panoWidth / panoRangeX * relativeHeading );
var hotspotY = Math.round( panoHeight / 2 - panoHeight / panoRangeY * relativePitch );
// Just in case we endup out of range
while (hotspotX < 0) { hotspotX += panoWidth; }
while (hotspotX > panoWidth) { hotspotX -= panoWidth; }
while (hotspotY < 0) { hotspotY += panoHeight; }
while (hotspotY > panoHeight) { hotspotY -= panoHeight; }
alert("Hotspot is at: " + hotspotX + ", " + hotspotY);
I hope this helps!