Angle Between Screen Elements

I seem to be struggling with calculating the angle between image elements on a 2D screen.

The goal is to effectively draw a line with a rectangle by rotating it toward the object and then setting the height equal to the distance between the objects. The only problem is that whenever I calculate the angle like this:

var vecA = this.entity.getPosition().normalize();
    var vecB = this.target.getPosition().normalize();
    var dot = vecA.dot(vecB);
    var angleInRadians = Math.acos(dot);
    var angle = angleInRadians * pc.math.RAD_TO_DEG;
    console.log(angle);
        this.entity.rotateLocal(0,0,angle);

The resulting angle is off by about 50 degrees. Am I going about this the wrong way?

Hi @eproasim,

The code seems correct to get the angle between two world positions. Not sure about the offset, if it’s coming from a local translation or not.

Though, thinking, if the offset is always 50 degrees then you can add it to the final angle and then wrap the value between 0 and 360.

1 Like

Hi @Leonidas!

I did some additional testing, and unfortunately 50 degrees is not the only offset. They seem to be random. One idea is that it could be calculating on the wrong axis, but that seems unlikely. I placed two elements at 0 on the Y axis and experimented with different distances. The angles still seemed random, and it never actually came out to 90 degrees. Not even close

Hi,@eproasim if I understand correctly,the angle you calculate is not what you are looking for:

Snipaste_2020-12-22_10-13-38

you calculate angle IOJ but you need to know the angle MIJ,am I right :thinking:

2 Likes

Hi @FBplus !

I think that’s almost right. angles

I think I actually want to measure PIJ. Do you have tips on calculating that angle?

@eproasim First you could get vector IJ which is equal to positionJ - positionI,then you could get the angle between vector IP (which is (0,1,0) in this case) and vector IJ(don’t forget to normalize) by dot product just like what you did.you can give it a try and see if it works :grinning:

1 Like

Hi @FBplus,

It’s much much closer now! Thank you for the assistance! I think I’m going wrong in calculating a vector somewhere though. Here is what I have now.

    var yVec = new pc.Vec3(0,1,0).normalize();
    var vecA = this.entity.getPosition().normalize();
    var vecB = this.target.getPosition().normalize();
    var posVector = vecB.sub(vecA).normalize();
    var dot = posVector.dot(yVec);
    var angleInRadians = Math.acos(dot);
    var angle = angleInRadians * pc.math.RAD_TO_DEG;
    console.log(angle);
        

    this.entity.rotateLocal(0,0,angle);

The result is only off by a few degrees, and I have confirmed that my pivots are in the center of the circles. Any ideas?

@eproasim What’s the entity and target in that image?like this?
image

1 Like

@FBplus

image

I hope this helps! I’m currently just testing the rotation. Eventually the rectangle will be aligned with the other circles.

@eproasim It looks OK.What about the pivot of the entity? Is it at the center bottom of the rectangle just like you paint on the image?

1 Like

@FBplus

That is correct. The pivot is at the bottom center like it is painted.

Made an example:

https://playcanvas.com/project/749395/overview/connect-2-elements

4 Likes

Try to use getLocalPosition() instead of getPosition(),I don’t know why but it just works :joy:
You can check out what LeXXik did,It looks great :star_struck:

2 Likes

@FBplus,
@LeXXik,

Thank you very much for the assistance. It worked! Like in LeXXik’s example, I did have to declare a new pc.Vec3() variable ahead of time then use .copy() later in the script to calculate my rotation based on getLocalPosition(). Not using .copy() will move the target to the origin entity’s position.

Any ideas why only getLocalPosition() works?

2 Likes

I think that’s because UI elements belonging to a 2D screen are always positioned in local space in relation to that screen. And the screen is rendered in screen space, so a world position like the one returned by the getPosition() method doesn’t really make sense in this case.

2 Likes