Orientation, location, and .contains()

I’m creating an experiment online in which I have an array of ShapeStims with vertices that are off-centre, and each stimulus different in orientation from the others, such that the stimuli are arranged in a circle around the central point of the screen. I have another, target stimulus that I want to modify depending on which of my ShapeStims the participant currently has their mouse over. I thought this would be easy enough to get happening by using a simple for loop that runs each frame, testing whether each of the ShapeStims contains the cursor, and updating the value of the relevant dimension of the target stimulus accordingly.

The problem I am running into is that the target stimulus is only updating when the mouse is over the location of the ShapeStim with orientation 0 (i.e., the “original” position of each of the stimuli, prior to rotation). Since I haven’t had the same problem before when the locations, rather than orientations, of stimuli in an array differ from one another, and I also haven’t had the problem when doing something similar with orientations in the python version of PsychoPy (though admittedly many versions ago), this leads me to wonder whether changing the orientation of my ShapeStims is somehow not updating their locations in psychoJS in the way I am expecting.

Is this a problem anyone has come across before? If so, did you manage to find a solution?

So, to answer my own question: The psychoJS code for ShapeStim currently has this comment on line 227, where the position is being calculated:

// TODO take the orientation into account

To get the behaviour I wanted, I’ve thus created a function that rotates an x, y coordinate, and used that to modify the positions of the individual vertices instead of directly modifying the orientation of the stimuli. The function is pretty basic, but if anyone else wants to do the same thing and is feeling lazy, it is as follows:

function XYRotate(coords, theta){ // theta is in degrees
  var thetaRAD = theta * Math.PI / 180; // convert angle to radians
  return([coords[0]*Math.cos(thetaRAD)-coords[1]*Math.sin(thetaRAD),
  coords[0]*Math.sin(thetaRAD)+coords[1]*Math.cos(thetaRAD)]);
}