Finding a minimum bounding sphere for a frustum - algorithm

I have a frustum (truncated pyramid) and I need to compute a bounding sphere for this frustum that's as small as possible. I can choose the centre to be right in the centre of the frustum and the radius be the distance to one of the "far" corners, but that usually leaves quite a lot of slack around the narrow end of the frustum
This seems like simple geometry, but I can't seem to figure it out. Any ideas?

This is probably not the answer you're looking for, but you could compute all the verts of the frustum and plug them into a general minimum bounding sphere algorithm, like the miniball implementation.

Well, there's http://www.cgafaq.info/wiki/Minimal_enclosing_sphere of course (via Google).
I'd think there are two possibilities. One (if the frustum is very flat) would be that the opposite points of the base become opposite points on the sphere. The other (if the frustum is very tall) would be that opposite points of the frustum would be on the sphere and you'd figure out the sphere from those four points (one point on the base, one opposite the first on the base, one opposite the first on the higher square, one adjacent the first on the higher square).
Figure out the first sphere. If the frustum fits in it, that's your answer. Otherwise, the second sphere would be your answer.

There are several algorithms and implementations out there for this problem (see also this post).
For 2D and 3D, Gärtner's implementation is probably the fastest.
For higher dimensions (up to 10,000, say), take a look at https://github.com/hbf/miniball, which is the implementation of an algorithm by Gärtner, Kutz, and Fischer (note: I am one of the co-authors).
For very, very high dimensions, core-set (approximation) algorithms will be faster.
In your particular application, you may want to try either of the first two algorithms. Both run in O(n) with a very small constant and are numerically stable.

The way to do this is to find a sphere that fits 4 points on your frustum. If this is a proper frustum (a truncated pyramid - my bad I was assuming a cylindrical fristum), then you get two points from opposite corners of the top quad, and the other two from the bottom quad, out of phase with the top two. Then use this to get your sphere.

Well let's solve with math.
Using right hand Y up coordinate system (forward is –Z axis), for frustum with viewport width w, height h, near plane n, far plane f, X axis field of view angle fov, then the minimal bounding sphere is
k = sqrt(1+(h/w)^2) * tan⁡(fov/2)
if( k^2 >= (f-n)/(f+n) )
{
C = (0, 0, -f)
R = f*k
}
else
{
C = (0, 0, -0.5 * (f+n) * (1+k^2))
R = 0.5 * sqrt( (f-n)^2 + 2*(f^2+n^2)*k^2 + (f+n)^2*k^4 )
}
C is the center of the sphere, in view space, and R is radius.
I put details in my blog if you are interested:
https://lxjk.github.io/2017/04/15/Calculate-Minimal-Bounding-Sphere-of-Frustum.html

Any set of four noncoplanar points defines a sphere. Assuming you're using a four-sided pyramid for your frustum, there are 70 possible sets of four points. Try all 70 spheres and see which is the smallest.
Given that your frustum probably has some symmetries, you can probably pick the four points on opposite corners and use plinth's solution.

You need to find a point on a "vertical" line down the center of the frustum where the distance to an edge on the bottom and top of the frustum (assuming it's symmetrical) is the same.
solve such that a point on the bottom is Xb, Yb, Zb, a point on the top is Xt, Yt, Zt and the line is a point Xp, Yp, Zp plus a vector Ax, By, Cz.
so solve the equation
sqrt( (Xb - (Xp + VAx) )^2 + (Yb - (Yp + VBy))^2 + (Zb - (Zp + VCy))^2) =
sqrt( (Xt - (Xp + VAx) )^2 + (Yt - (Yp + VBy))^2 + (Zt - (Zp + VCy))^2).
The only variable in there is the scalar V.

Strictly speaking (according to this) the base of the frustum can be any polygon and, also strictly speaking, that polygon doesn't even have to be convex. That said, to get a general solution to the problem, I think you might need to use (almost) all the vertices as suggested above. There might be special cases, though, whose solution might (as suggested above) only require the comparison of a couple of spheres. I like the link by Anthony above: Megiddo provides a transformation that he claims yields a solution in O(n) (!) time. Not bad !

Related

How to find collision center of two rectangles? Rects can be rotated

I've just implemented collision detection using SAT and this article as reference to my implementation. The detection is working as expected but I need to know where both rectangles are colliding.
I need to find the center of the intersection, the black point on the image above (but I don't have the intersection area neither). I've found some articles about this but they all involve avoiding the overlap or some kind of velocity, I don't need this.
The information I've about the rectangles are the four points that represents them, the upper right, upper left, lower right and lower left coordinates. I'm trying to find an algorithm that can give me the intersection of these points.
I just need to put a image on top of it. Like two cars crashed so I put an image on top of the collision center. Any ideas?
There is another way of doing this: finding the center of mass of the collision area by sampling points.
Create the following function:
bool IsPointInsideRectangle(Rectangle r, Point p);
Define a search rectangle as:
TopLeft = (MIN(x), MAX(y))
TopRight = (MAX(x), MAX(y))
LowerLeft = (MIN(x), MIN(y))
LowerRight = (MAX(x), MIN(y))
Where x and y are the coordinates of both rectangles.
You will now define a step for dividing the search area like a mesh. I suggest you use AVG(W,H)/2 where W and H are the width and height of the search area.
Then, you iterate on the mesh points finding for each one if it is inside the collition area:
IsPointInsideRectangle(rectangle1, point) AND IsPointInsideRectangle(rectangle2, point)
Define:
Xi : the ith partition of the mesh in X axis.
CXi: the count of mesh points that are inside the collision area for Xi.
Then:
And you can do the same thing with Y off course. Here is an ilustrative example of this approach:
You need to do the intersection of the boundaries of the boxes using the line to line intersection equation/algorithm.
http://en.wikipedia.org/wiki/Line-line_intersection
Once you have the points that cross you might be ok with the average of those points or the center given a particular direction possibly. The middle is a little vague in the question.
Edit: also in addition to this you need to work out if any of the corners of either of the two rectangles are inside the other (this should be easy enough to work out, even from the intersections). This should be added in with the intersections when calculating the "average" center point.
This one's tricky because irregular polygons have no defined center. Since your polygons are (in the case of rectangles) guaranteed to be convex, you can probably find the corners of the polygon that comprises the collision (which can include corners of the original shapes or intersections of the edges) and average them to get ... something. It will probably be vaguely close to where you would expect the "center" to be, and for regular polygons it would probably match exactly, but whether it would mean anything mathematically is a bit of a different story.
I've been fiddling mathematically and come up with the following, which solves the smoothness problem when points appear and disappear (as can happen when the movement of a hitbox causes a rectangle to become a triangle or vice versa). Without this bit of extra, adding and removing corners will cause the centroid to jump.
Here, take this fooplot.
The plot illustrates 2 rectangles, R and B (for Red and Blue). The intersection sweeps out an area G (for Green). The Unweighted and Weighted Centers (both Purple) are calculated via the following methods:
(0.225, -0.45): Average of corners of G
(0.2077, -0.473): Average of weighted corners of G
A weighted corner of a polygon is defined as the coordinates of the corner, weighted by the sin of the angle of the corner.
This polygon has two 90 degree angles, one 59.03 degree angle, and one 120.96 degree angle. (Both of the non-right angles have the same sine, sin(Ɵ) = 0.8574929...
The coordinates of the weighted center are thus:
( (sin(Ɵ) * (0.3 + 0.6) + 1 - 1) / (2 + 2 * sin(Ɵ)), // x
(sin(Ɵ) * (1.3 - 1.6) + 0 - 1.5) / (2 + 2 * sin(Ɵ)) ) // y
= (0.2077, -0.473)
With the provided example, the difference isn't very noticeable, but if the 4gon were much closer to a 3gon, there would be a significant deviation.
If you don't need to know the actual coordinates of the region, you could make two CALayers whose frames are the rectangles, and use one to mask the other. Then, if you set an image in the one being masked, it will only show up in the area where they overlap.

Intersection of a 3D Grid's Vertices

Imagine an enormous 3D grid (procedurally defined, and potentially infinite; at the very least, 10^6 coordinates per side). At each grid coordinate, there's a primitive (e.g., a sphere, a box, or some other simple, easily mathematically defined function).
I need an algorithm to intersect a ray, with origin outside the grid and direction entering it, against the grid's elements. I.e., the ray might travel halfway through this huge grid, and then hit a primitive. Because of the scope of the grid, an iterative method [EDIT: (such as ray marching) ]is unacceptably slow. What I need is some closed-form [EDIT: constant time ]solution for finding the primitive hit.
One possible approach I've thought of is to determine the amount the ray would converge each time step toward the primitives on each of the eight coordinates surrounding a grid cell in some modular arithmetic space in each of x, y, and z, then divide by the ray's direction and take the smallest distance. I have no evidence other than intuition to think this might work, and Google is unhelpful; "intersecting a grid" means intersecting the grid's faces.
Notes:
I really only care about the surface normal of the primitive (I could easily find that given a distance to intersection, but I don't care about the distance per se).
The type of primitive intersected isn't important at this point. Ideally, it would be a box. Second choice, sphere. However, I'm assuming that whatever algorithm is used might be generalizable to other primitives, and if worst comes to worst, it doesn't really matter for this application anyway.
Here's another idea:
The ray can only hit a primitive when all of the x, y and z coordinates are close to integer values.
If we consider the parametric equation for the ray, where a point on the line is given by
p=p0 + t * v
where p0 is the starting point and v is the ray's direction vector, we can plot the distance from the ray to an integer value on each axis as a function of t. e.g.:
dx = abs( ( p0.x + t * v.x + 0.5 ) % 1 - 0.5 )
This will yield three sawtooth plots whose periods depend on the components of the direction vector (e.g. if the direction vector is (1, 0, 0), the x-plot will vary linearly between 0 and 0.5, with a period of 1, while the other plots will remain constant at whatever p0 is.
You need to find the first value of t for which all three plots are below some threshold level, determined by the size of your primitives. You can thus vastly reduce the number of t values to be checked by considering the plot with the longest (non-infinite) period first, before checking the higher-frequency plots.
I can't shake the feeling that it may be possible to compute the correct value of t based on the periods of the three plots, but I can't come up with anything that isn't scuppered by the starting position not being the origin, and the threshold value not being zero. :-/
Basically, what you'll need to do is to express the line in the form of a function. From there, you will just mathematically have to calculate if the ray intersects with each object, as and then if it does make sure you get the one it collides with closest to the source.
This isn't fast, so you will have to do a lot of optimization here. The most obvious thing is to use bounding boxes instead of the actual shapes. From there, you can do things like use Octrees or BSTs (Binary Space Partitioning).
Well, anyway, there might be something I am overlooking that becomes possible through the extra limitations you have to your system, but that is how I had to make a ray tracer for a course.
You state in the question that an iterative solution is unacceptably slow - I assume you mean iterative in the sense of testing every object in the grid against the line.
Iterate instead over the grid cubes that the line intersects, and for each cube test the 8 objects that the cube intersects. Look to Bresenham's line drawing algorithm for how to find which cubes the line intersects.
Note that Bresenham's will not return absolutely every cube that the ray intersects, but for finding which primitives to test I'm fairly sure that it'll be good enough.
It also has the nice properties:
Extremely simple - this will be handy if you're running it on the GPU
Returns results iteratively along the ray, so you can stop as soon as you find a hit.
Try this approach:
Determine the function of the ray;
Say the grid is divided in different planes in z axis, the ray will intersect with each 'z plane' (the plane where the grid nodes at the same height lie in), and you can easily compute the coordinate (x, y, z) of the intersect points from the ray function;
Swipe z planes, you can easily determine which intersect points lie in a cubic or a sphere;
But the ray may intersects with the cubics/spheres between the z planes, so you need to repeat the 1-3 steps in x, y axises. This will ensure no intersection is left off.
Throw out the repeated cubics/spheres found from x,y,z directions searches.

calculate the area of a polygon in ruby

I have an array of latitude/longitude coordinate pairs that represent a polygon. I'm trying to determine the total area within that polygon. How would I go about doing that in Ruby?
Here's an example array of the polygon:
[[37.7663613767094, -122.452969210084], [37.7674219449606, -122.444718340349], [37.7701838510542, -122.445330289514], [37.7709974013834, -122.439159589248], [37.7700761930893, -122.438861402472], [37.7703501163684, -122.436868738421], [37.7712650571321, -122.437078116573], [37.7736056746515, -122.437533130227], [37.7714671036087, -122.453964210266], [37.7663613767094, -122.452969210084]]
It probably doesn't matter that much on the language. You can make use of the formula mentioned in here for calculating the area of a polygon:
http://mathworld.wolfram.com/PolygonArea.html
Assuming your points are (x1, y1) (x2, y2) .. (xn, yn) and they enclose a small area:
Area = 0.5 * (x1 * y2 - x2 * y1 + x2 * y3 - x3 * y2 ..... + xn * y1 - x1 * yn)
Note: This won't work for larger areas, for which you need to use more complex method to calculate the area, which involves angular co-ordinates. But, this does the job for small areas, which can be assumed to be planar.
Edit:
To get area in sq miles, you can do the following, from there, convert to whatever units you want.
areaInSqMiles = Area * (60 * 60 * 1.15 * 1.15)
language independent solution:
GIVEN: a polygon can ALWAYS be composed by n-2 triangles that do not overlap (n = number of points OR sides). 1 triangle = 3 sided polygon = 1 triangle; 1 square = 4 sided polygon = 2 triangles; etc ad nauseam QED
therefore, a polygon can be reduced by "chopping off" triangles and the total area will be the sum of the areas of these triangles. try it with a piece of paper and scissors, it is best if you can visualize the process before following.
if you take any 3 consecutive points in a polygons path and create a triangle with these points, you will have one and only one of three possible scenarios:
resulting triangle is completely inside original polygon
resulting triangle is totally outside original polygon
resulting triangle is partially contained in original polygon
we are interested only in cases that fall in the first option (totally contained).
every time we find one of these, we chop it off, calculate its area (easy peasy, wont explain formula here) and make a new polygon with one less side (equivalent to polygon with this triangle chopped off). until we have only one triangle left.
how to implement this programatically:
create an array of points. run the array making triangles from points x, x+1 and x+2. transform each triangle from a shape to an area and intersect it with area created from polygon. IF the resulting intersection is identical to the original triangle, then said triangle is totally contained in polygon and can be chopped off. remove x+1 from the array and start again from x=0. otherwise, move to next point x+1 in array.
additionally if you are looking to integrate with mappping and are starting from geopoints, you must convert from geopoints to screenpoints. this requires deciding a modelling and formula for earths shape (though we tend to think of the earth as a sphere, it is actually an irregular ovoid (eggshape), with dents. there are many models out there, for further info wiki.
You can use this library which wraps GEOS (a C geospatial library itself a port of the JTS).
https://github.com/dark-panda/ffi-geos
This library can handle the calculations in coordinate space and takes care of the approximations.
Depending on how much accuracy you need I would project the data first to an appropriate projection (not Mercator). Then calculate your area
There is an awesome example on how to multiply verticies. Essentially exactly what you would like to do!!
http://www.wikihow.com/Calculate-the-Area-of-a-Polygon
Some techniques for this include integration (divide the polygon into latitudinal strips and integrate. You can also project onto a flat surface and calculate that area.

Formula to determine whether a line form by 2 geo points (lat, lon) intersects geo region (circle)?

It does not need to be very accurate. Does anyone know a good way to do this?
any help is much appreciated.
When you say “it does not need to be very accurate” you don’t say how inaccurate a solution you’re prepared to accept. Also, you don’t say how big the geographic region under consideration is likely to be. These two criteria make a big difference to the kind of approach that needs to be taken.
With a small regions (a few kilometres, say), a flat approximation may be good enough (for example, the Mercator projection) and some of the other responses tell you how to do that. With larger regions you have to take the Earth’s sphericity into account. And if you want inaccuracy less than a percent or so, you need to take the eccentricity of Earth into account.
I’m going to assume for the purposes of this answer that a spherical approximation is good enough, and that your points are at similar enough altitudes that we don’t need to worry about their heights.
You can convert a geographical point (ψ, λ) to Cartesian Earth-centred coordinates using the transformation
(ψ, λ) → (a cos(ψ) cos(λ), a cos(ψ) sin(λ), a sin(ψ))
where a is the mean radius of the Earth (6,371 km). So let’s suppose that the two points that define your line are p₀ and p₁; then the shortest line through p₀ and p₁ is a great circle, which defines a plane that slices the Earth into two halves, with normal n = p₀ × p₁.
Now we need to find the border of the circular region. Suppose the centre of this region is at c and that the surface radius of the region is s. Then the straight-line radius of the region is r = a sin(s/a). We’ll also need the true centre of the circular region, c’ = c cos(s/a). (This point is buried deep underground!)
We’d like to intersect the two circles and solve for the points of intersection. Unfortunately, because of numerical imprecision, the chances are that this procedure will never find any solutions because the imprecise circles will miss each other in 3 dimensions. So I suggest the following procedure: intersect the planes of the two circles, getting the dotted line shown below (unless c’ × n = 0 in which case the two circles are parallel and either c’ = o, in which case they are coincident, or else they do not intersect). Then intersect the line with the circular region.
This two-step procedure reduces the problem to two dimensions, and guarantees that a solution will be found even if numerical imprecision makes the two circles miss in 3 dimensions.
If you need more accuracy than this, then you might need to use geodetic coordinates on a reference ellipsoid such as WGS 1984.
I'd say find the closest point on the line to the center of the circle, then determine whether that point is within the circle (i.e. the distance in question is less than or equal to the circle's radius).
Outline for solving the problem: assume the Earth is a sphere of radius one centered at the origin. Convert all three lat, lon points to 3D coordinates. The two points of the line plus the origin define a plane; intersect that plane with the sphere of radius d centered on the other point. If there is no plane-sphere intersection, then the answer is the line does not intersect the region. If there is a plane-sphere intersection, then the problem is simplified to intersecting the circular region defined by the plane-sphere intersection with the shortest circular arc on the plane going between the end points of the line and centered at the origin. This is a straightforward 2D problem if you convert to the coordinate system of the plane.
This question is too vague to be answered precisely. What do you mean by
a line form by 2 geo points (lat, lon)
This can be either a great circle going through them (also called orthodrome) or it a can be a linear function of spherical coordinates (loxodrome).
BTW, I assume your circle is a circle on the surface of the sphere, right?
Assuming line is formed by points (x1, y1) and (x2, y2), and circle has radius r with origin (0,0):
Calculate:
Incidence = r^2 * [(x2 - x1)^2 + (y2 - y1)^2] - (x1 * y2 - x2 * y1)^2
Then, from the value of Incidence, we can determine the following:
Incidence < 0: No intersection
Incidence = 0: Tangent (intersection at 1 point on circle)
Incidence > 0: Intersection
It's likely your circle is not at the origin (0,0), so to fix this, just add the origin coordinates from your line coordinates in the equation above. So, if the circle is at (x3, y3), x1 in the above equation would become x1 + x3. Likewise, y1 would be y1 + y3, and the same goes for x2 and y2.
For more info check out this link

What algorithm can I use to determine points within a semi-circle?

I have a list of two-dimensional points and I want to obtain which of them fall within a semi-circle.
Originally, the target shape was a rectangle aligned with the x and y axis. So the current algorithm sorts the pairs by their X coord and binary searches to the first one that could fall within the rectangle. Then it iterates over each point sequentially. It stops when it hits one that is beyond both the X and Y upper-bound of the target rectangle.
This does not work for a semi-circle as you cannot determine an effective upper/lower x and y bounds for it. The semi-circle can have any orientation.
Worst case, I will find the least value of a dimension (say x) in the semi-circle, binary search to the first point which is beyond it and then sequentially test the points until I get beyond the upper bound of that dimension. Basically testing an entire band's worth of points on the grid. The problem being this will end up checking many points which are not within the bounds.
Checking whether a point is inside or outside a semi-circle (or a rectangle for that matter) is a constant-time operation.
Checking N points lie inside or outside a semi-circle or rectangle is O(N).
Sorting your N points is O(N*lg(N)).
It is asymptotically faster to test all points sequentially than it is to sort and then do a fast culling of the points based on a binary search.
This may be one of those times where what seems fast and what is fast are two different things.
EDIT
There's also a dead-simple way to test containment of a point in the semi-circle without mucking about with rotations, transformations, and the like.
Represent the semi-circle as two components:
a line segment from point a to b representing the diameter of the semi-circle
an orientation of either left-of or right-of indicating that the semi-circle is either to the left or right of line segment ab when traveling from a to b
You can exploit the right-hand rule to determine if the point is inside the semicircle.
Then some pseudo-code to test if point p is in the semi-circle like:
procedure bool is_inside:
radius = distance(a,b)/2
center_pt = (a+b)/2
vec1 = b - center_pt
vec2 = p - center_pt
prod = cross_product(vec1,vec2)
if orientation == 'left-of'
return prod.z >= 0 && distance(center_pt,p) <= radius
else
return prod.z <= 0 && distance(center_pt,p) <= radius
This method has the added benefit of not using any trig functions and you can eliminate all square-roots by comparing to the squared distance. You can also speed it up by caching the 'vec1' computation, the radius computation, center_pt computation, and reorder a couple of the operations to bail early. But I was trying to go for clarity.
The 'cross_product' returns an (x,y,z) value. It checks if the z-component is positive or negative. This can also be sped up by not using a true cross product and only calculating the z-component.
First, translate & rotate the semi-circle so that one end is on the negative X-axis, and the other end is on the positive X-axis, centered on the origin (of course, you won't actually translate & rotate it, you'll just get the appropriate numbers that would translate & rotate it, and use them in the next step).
Then, you can treat it like a circle, ignoring all negative y-values, and just test using the square root of the sum of the squares of X & Y, and see if it's less than or equal to the radius.
"Maybe they can brute force it since they have a full GPU dedicated to them."
If you have a GPU at your disposal, then there are more ways to do it. For example, using a stencil buffer:
clear the stencil buffer and set the stencil operation to increment
render your semicircle to the stencil buffer
render your points
read back the pixels and check the values at your points
the points that are inside the semicircle would have been incremented twice.
This article describes how stencil buffers can be used in OpenGL.
If there's a standard algorithm for doing this, I'm sure someone else will come up with it, but if not: you could try sorting the points by distance from the center of the circle and iterating over only those whose distance is less than the semicircle's radius. Or if computing distance is expensive, I'd just try finding the bounding box of the semicircle (or even the bounding square of the circle of which the semicircle is part) and iterating over the points in that range. To some extent it depends on the distribution of the points, i.e. do you expect most of them or only a small fraction of them to fall within the semicircle?
You can find points in a circle and points on one side of a given slope, right?
Just combine the two.
Here's part of a function I wrote do get a cone firing arc for a weapon in a tile based game.
float lineLength;
float lineAngle;
for(int i = centerX - maxRange; i < centerX + maxRange + 1; i++){
if(i < 0){
continue;
}
for(int j = centerY - maxRange; j < centerY + maxRange + 1; j++){
if(j < 0){
continue;
}
lineLength = sqrt( (float)((centerX - i)*(centerX - i)) + (float)((centerY - j)*(centerY - j)));
lineAngle = lineAngles(centerX, centerY, forwardX, forwardY, centerX, centerY, i, j);
if(lineLength < (float)maxRange){
if(lineAngle < arcAngle){
if( (float)minRange <= lineLength){
AddToHighlightedTiles(i,j);
}
}
}
}
}
The variables should be self explanatory and the line angles function takes 2 lines and finds the angle between them. The forwardX and forwardY is just one tile in the correct direction from the center X and Y based on what angle you're pointing in. Those can be gotten easily with a switch statement.
float lineAngles(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){
int a = x2 - x1;
int b = y2 - y1;
int c = x4 - x3;
int d = y4 - y3;
float ohSnap = ( (a * c) + (b * d) )/(sqrt((float)a*a + b*b) * sqrt((float)c*c + d*d) );
return acos(ohSnap) * 180 / 3.1415926545f;
}
It would appear that a simple scheme will work here.
Reduce the number of points in the set, by first computing the convex hull. Only the points on the convex hull will contribute to any interaction with any convex bounding shape. So retain only the subset of points on the perimeter of the hull.
It can easily be argued that the minimal radius bounding semi-circle must have one edge (two points) of the convex hull coincident along the diameter of the semi-circle. I.e., if some edge of the hull does not lie in the diameter, then there exists a different semi-circle with smaller diameter that contains the same set of points.
Test each edge in sequence. (A convex hull often has relatively few edges, so this will go quickly.) Now it becomes a simple 1-d minimization problem. If we choose to assume the edge in question lies on the diameter, then we merely need to find the center of the sphere. It must lie along the current line which we are considering to be the diameter. So as a function of the position of the point along the current diameter, just find the point which lies farthest away from the nominal center. By minimizing that distance, we find the radius of the minimal semi-circle along that line as a diameter.
Now, just choose the best of the possible semi-circles found over all edges of the convex hull.
If your points have integer co-ordinates, the fastest solution may be a lookup table. Since a semicircle is convex, for each y co-ordinate, you get a fixed range of x, so each entry in your lookup table gives maximum and minimum X co-ordinates.
Of course you still need to precalculate the table, and if your semicircle isn't fixed, you may be doing that a lot. That said, this is basically one part of what would once have been done to render a semicircle - the full shape would be rendered as a series of horizontal spans by repeatedly calling a horizontal line drawing function.
To calculate the spans in the first place (if you need to do it repeatedly), you'd probably want to look for an old copy of Michael Abrash's Zen of Graphics Programming. That described Bresenhams well-known line algorithm, and the not-so-well-known Hardenburghs circle algorithm. It shouldn't be too hard to combine the span-oriented versions of the two to quickly calculate the spans for a semi-circle.
IIRC, Hardenburgh uses the x^2 + y^2 = radius^2, but exploits the fact that you're stepping through spans to avoid calculating square roots - I think it uses the fact that (x+1)^2 = x^2 + 2x + 1 and (y-1)^2 = y^2 - 2y + 1, maintaining running values for x, y, x^2 and (radius^2 - y^2), so each step only requires a comparison (is the current x^2 + y^2 too big) and a few additions. It's done for one octant only (the only way to ensure single-pixel steps), and extended to the full circle through symmetry.
Once you have the spans for the full circle, it should be easy to use Bresenhams to cut off the half you don't want.
Of course you'd only do all this if you're absolutely certain that you need to (and that you can work with integers). Otherwise stick with stbuton.
translate the center of the arc to the origin
compute angle between ordinate axis and end points of radii of semi-cirlce
translate the point in question by same dx,dy
compute distance from origin to translated x,y of point, if d > radius of circle/arc eliminate
compute angle between ordinate axis and end point
if angle is not between starting and ending arc of semi-cirlce, eliminate
points remaning should be inside semi-circle
I guess someone found the same solution as me here but I have no code to show as its pretty far in my memory...
I'd do it by steps...
1. I'd look if i'm within a circle... if yes look on which side of the circle.
2. By drawing a normal vector that come from the vector made by the semi-sphere. I could know if I'm behind or in front of the vector...and if you know which side is the semi sphere and which side is the void...It will be pretty damn easy to find if you're within the semi sphere. You have to do the dot product.
I'm not sure if it's clear enough but the test shouldn't be that hard to do...In the end you have to look for a negative or positive value...if it's 0 you're on the vector of the semisphere so it's up to you to say if it's outside or inside the semi-sphere.
The fastest way to do this will depend on your typical data. If you have real-world data to look at, do that first. When points are outside the semi-circle, is it usually because they are outside the circle? Are your semi-circles typically thin pie slices?
There are several ways to do this with vectors. You can scale the circle to a unit circle and use cross-products and look at the resultant vectors. You can use dot-products and see how the prospective point lands on the other vectors.
If you want something really easy to understand, first check to make sure it's inside the circle, then get the angle and make sure it's between the angle of the two vectors that dictate the semi-circle.
Edit: I had forgotten that a semicircle is always half a circle. I was thinking of any arbitrary section of a circle.
Now that I have remembered what a semicircle is, here's how I would do that. It's similar to stbuton's solution, but it represents the semicircle differently.
I'd represent the semicircle as the unit vector that bisects the semicircle. You can easily get that from either one of the vectors that indicate the boundary of the semicircle (because they are 90 degrees away from the representation) by swapping x and y and negating one of them.
Now you just cross the vector created by subtracting the point to be tested from the circle's center. The sign of z tells you whether the point is in the semicircle, and the length of z can be compared against the radius.
I did all the physics for Cool Pool (from Sierra Online). It's all done in vectors and it's filled with dots and crosses. Vectors solutions are fast. Cool Pool was able to run on a P60, and did reasonable breaks and even spin.
Note: For solutions where you're checking sqrt(xx+yy), don't even do the sqrt. Instead, keep the square of the radius around and compare against that.

Resources