how to check if a point is inside an angle of a circle

Started by
5 comments, last by lawnjelly 5 years, 1 month ago

hi,

like the subject above, how to check if a point/coordinates is inside an arbitrary angle, 

image.png.dc4441bc4c6b36dfbab69e159e747aa3.png

the rendering is in OpenGL orthogonal therefore using 2D screen coordinates with the origin 0,0 is top left, 
In the screenshot above, P1 is inside the angle point therefore will be rendered and P2 is not.

What i am trying to do here is only display the part in the circle using the shaders depending on the angle. Like a circular progress bar or something.

Advertisement

I'd say, build the pie shape geometry at run time and submit that to the renderer. The  2D trigeometry or vector math seems straight forward. Are the equations in question here? A spline might be neat here as one of the sides of the dynamic pie shape.

You can subtract the center from the point, and consider this 2d vector, if normalized, as x coordinate being cosine and y coordinate being sine.

Then just immediately compare those trigonometric values againts the two reference contain angles trigonomteric values.

Its exactly like JohnnyCode explained, so here is a javascript code i have written a few years ago which does exactly that:


/**
  * <p>Normalizes an angle - bring it into 0 - 2 PI range</p>
  * <p>Does handle negative angles as well.</p>
  * @param rad {Number} Angle in radians
  * @returns {Number}
  */
radNormalize: function(rad) {
  while (rad < 0) {
    rad += TAU;
  }
  while (rad > TAU) {
    rad -= TAU;
  }
  return rad;
},

CircleShape.prototype.containsPoint = function (x, y) {
	var v = new Vec2(x - this.pos.x, y - this.pos.y);
	var angle = radNormalize(Math.atan2(v.y, v.x) - this.startAngle);
	var lenSquared = math.vec2Dot(v, v);
	var insideCircle = lenSquared <= this.radius * this.radius;
    var insideSegment = angle <= (this.endAngle - this.startAngle);
	return insideCircle && insideSegment;
};

 

As usual, you can do this without angles, and you probably should. Friends don't let friends use angles. :)

You are really trying to determine if a vector v is in the arc limited by two other vectors v1 and v2. Start by normalizing all the vectors so they have length 1. Now that we are looking at points on a circle, all you need to do is look at the points (*) v1, v2, v and see if they are in clockwise or anticlockwise order. The function ccw() here does the job: https://algs4.cs.princeton.edu/91primitives/

Or you can try to compute the area of the triangle whose vertices are v1, v2, v using a determinant and check what sign it comes out with. That's essentially the same method. Think about it whichever way seems more natural to you.

You can also use complex numbers to represent points and vectors in 2D. In that case, this code would do the trick:


#include <complex>

typedef std::complex<float> C;

bool is_between(C v, C v1, C v2) {
  v /= std::abs(v);
  v1 /= std::abs(v1);
  v2 /= std::abs(v2);
  return ((v - v1) * std::conj(v - v2)).imag() > 0;
}

(*)- I am being a loose with the distinction between points and vectors here, but non-mathematicians probably won't even notice.

 

13 hours ago, GoliathForge said:

I'd say, build the pie shape geometry at run time and submit that to the renderer. The  2D trigeometry or vector math seems straight forward. Are the equations in question here? A spline might be neat here as one of the sides of the dynamic pie shape.

Going further on this, you could just build a circle out of e.g. 360 triangles, then in the drawcall specify the number of triangles to draw, without needing to modify the geometry.

Another way for interesting health bar shapes might be to store the 'maximum angle' for each texel in a texture, then in the fragment shader simply compare a uniform 'health angle' against the stored value. You could then have complex shapes for no extra cost.

This topic is closed to new replies.

Advertisement