I am aiming to create the following (a directed arrow that connects two nodes) :
At the moment I have this (a quadratic bezier curve drawn from the center point of one node to the center of another):
(Note I have drawn the bezier above the nodes to show where it begins and ends)
I need a method - heuristic or otherwise - to calculate the point of intersection (circled in red, above) between the bezier curve and the node's (ellipse) circumference.
With this, I could calculate the angle between the node center and the point of intersection to draw the arrow head lines at the correct location and angle.
As a last resort, I could use the quadratic Bézier formula to generate a list of points that lie along the curve and also generate a list of points that lie on the circumference of the circle and use one of the two coordinates that have the least euclidian distance between each other as my intersection point. I'm hoping any answers can leverage geometry or whatever else to better solve it.
The general problem is uneasy as the intersection equation is quartic ((X(t)-Xc)² + (Y(t)-Yc)²=R²), where X and Y are quadratic polynomials). If you have a quartic solver handy you can use it but you'll have to select the right root.
A more reasonable approach is just to intersect the circle with the line segment between the control points. This is approximate but probably unnoticeable if the circle radius is small.
If you want more accuracy, perform one or two Newton's iterations from this point.
I recently came across a problem which is something like this
There are N disjoint (such that they do not touch or intersect) circles given by their center and radius, i.e. center = (x_i, y_i), radius = r_i. Then we have Q queries where a point (x, y) is given. For each query we need to find out the index i of the circle which contains that given point (-1 if no circle).
The constraints are roughly 1 <= N <= 10^5 and 1 <= Q <= 10^5. So a O(Q * log(N)) might be needed.
Apart from the straight-forward O(Q * N) solution the only better thing I can think of is keeping the leftmost and rightmost points of the circles as intervals in an array and then doing binary search to find out the intervals which contains the x-coordinate of the point, but more than one intervals may be overlapping and more than one circle may contain the point. So I'm not sure if that's going to work.
Any help would be highly appreciated. Thank you.
This can be solved as a nearest-neighbour query in N+1 dimensions.
Imagine a set of balls of a fixed radius in 3d, such that their intersection with the plane z=0 is exactly your set of circles. (The balls may intersect, it doesn't matter). Now a point that falls into a circle is necessarily closer to the centre of its corresponding ball than to centres of all other balls.
The nearest-neighbour problem is well studied. Space partitioning techniques work well with real life data, though worst-case performance is not so good.
Edit: since the query point in in the fixed plane z=0, the problem can be seen as a 2d nearest-neighbour problem with non-Euclidean distance function. The effective distance from a query point to the centre of a circle is
D = &sqrt;(d2+R2 - r2)
where d is the real distance, R is the ball radius (conmon for all balls) and r is the circle radius.
Another way to solve this is to build a power diagram of the set of circles. A power diagram is a plane subdivision. There are ways to efficiently answer queries of the form "which cell of a plane subdivision given point belongs to", for example, using Kirkpatrik's point location data structure.
The two approaches are similar, if not equivalent, because in the power diagram, the power of the point with respect to a circle is the square of D in the formula for distance (with R=0).
I know this is a quite old question but for the records....
You can solve it with matplotlib Circle
from matplotlib.patches import Circle as Cr
.................
self.my_mpl_circle = Cr(origin, radius)
......
def match_pos(self, coords):
return self.my_mpl_circle.contains_point(coords)
I've been trying to implement a Voronoi Diagram using Fortunes Algorithm. I understand how it works but I'm stuck at how to store the parabolic arcs.
I understand all this is needed for the parabola is the sweeplines' Y position and the sites position but I'm I don't understand what to do with it.
I found this equation online (via this site):
What is X in this equation?
I'd say that y = ax2 + bx + c is the equation of a parabola with vertical axis. In this case, a,b,c are given in more detail. ly is a parameter which describes the current position of the sweep line and therefore influences the shape of the parabola. So your equation describes a whole family of parabolas, with pj,x and pj,y being the coordinates of the point you actually store in your data structure.
Suppose that there is a parabola Y = aX^2 + bX + c, and it might be rotated as follow:
X = x.sin(phi) + y.cos(phi)
Y = x.cos(phi) - y.sin(phi)
phi = rotation angle
We wish to fit it on a border (e.g. inner border of an eyelid, figure below). The problem is that how we can change the parabola in each iteration such that it minimizes a cost function. We know that the parabola can be in different rotation and its origin may vary in the search region. Note that the there are two given points which the fitted parabola should passes through them (e.g. the white squares in fig below). So, In each iteration we can compute a, b and c by the two given points and the origin point (three equations and three variables).
The question is how we can reach the goal in minimum iteration (not to test all the possibilities, i.e. all angles and all positions in the search region).
Any idea will be appreciated.
#woodchips: I think this is a programming problem, and he asked a solution for the implementation.I definitely disagree with you.
A possible solution would be to first search along the vertical line which is orthogonal to the line between the two given points. And also you can vary the angle in this interval. As the nature of your problem (the border of eyelid), you can limit the angle variation between -pi/4 and pi/4. After you find the minimum cost for a position in this vertical line, you can search along the horizontal line and do similar tasks.
Why not use regression to fit a parabola to several points in the target shape? Then you could use which ever algorithm you wanted to get an approximate solution. Newton's method converges pretty fast. The optimization here is on the coefficients in the approximate parabolas.
How can I find the largest circle that can fit inside a concave polygon?
A brute force algorithm is OK as long as it can handle polygons with ~50 vertices in real-time.
The key to solving this problem is first making an observation: the center of the largest circle that will fit inside an arbitrary polygon is the point that is:
Inside the polygon; and
Furthest from any point on the edges of the polygon.
Why? Because every point on the edge of a circle is equidistant from that center. By definition, the largest circle will have the largest radius and will touch the polygon on at least two points so if you find the point inside furthest from the polygon you've found the center of the circle.
This problem appears in geography and is solved iteratively to any arbitrary precision. Its called the Poles of Inaccessibility problem. See Poles of Inaccessibility: A Calculation Algorithm for the Remotest Places on Earth.
The basic algorithm works like this:
Define R as a rectilinear region from (xmin,ymin) to (xmax,ymax);
Divide R into an arbitrary number of points. The paper uses 21 as a heuristic (meaning divide the height and width by 20);
Clip any points that are outside the polygon;
For the remainder find the point that is furthest from any point on the edge;
From that point define a new R with smaller intervals and bounds and repeat from step 2 to get to any arbitrary precision answer. The paper reduces R by a factor of the square root of 2.
One note, How to test if a point is inside the polygon or not: The simplest solution to this part of the problem is to cast a ray to the right of the point. If it crosses an odd number of edges, it's within the polygon. If it's an even number, it's outside.
Also, as far as testing the distance to any edge there are two cases you need to consider:
The point is perpendicular to a point on that edge (within the bounds of the two vertices); or
It isn't.
(2) is easy. The distance to the edge is the minimum of the distances to the two vertices. For (1), the closest point on that edge will be the point that intersects the edge at a 90 degree angle starting from the point you're testing. See Distance of a Point to a Ray or Segment.
In case anyone is looking for a practical implementation, I designed a faster algorithm that solves this problem for a given precision and made it a JavaScript library. It's similar to the iterative grid algorithm described by #cletus, but it's guaranteed to obtain global optimum, and is also 20-40 times faster in practice.
Check it out: https://github.com/mapbox/polylabel
An O(n log(n)) algorithm:
Construct the Voronoi Diagram of the edges in P. This can be done with, for example, Fortunes algorithm.
For Voronoi nodes (points equidistant to three or more edges) inside P;
Find the node with the maximum distance to edges in P. This node is the centre of the maximum inscribed circle.
Summary: In theory, this can be done in O(n) time. In practice you can do it in O(n log n) time.
Generalized Voronoi diagrams.
If you consider the vertices and edges of the polygon as a set of sites and tessellate the interior into the "nearest neighbor cells" then you get the so-called (generalized) Voronoi diagram. The Voronoi diagram consists of nodes and edges connecting them. The clearance of a node is the distance to its defining polygon faces.
(Here the polygon even has holes; the principle still works.)
The key observation now is that the center of the maximum inscribed circle touches three faces (vertices or edges) of the polygon, and no other face can be closer. So the center has to lie on a Voronoi node, i.e, the node with the largest clearance.
In the example above the node that marks the center of the maximum inscribed circle touches two edges and a vertex of the polygon.
The medial axis, by the way, is the Voronoi diagram with those Voronoi edges removed that emanate from reflex vertices. Hence, the center of the maximum inscribed circle also lies on the medial axis.
Source: A blog article of mine that deals with generalizations of maximum inscribed circles at some point. There you can find more on Voronoi diagrams and their relation to maximum inscribed circles.
Algorithms & implementations.
You could actually compute the Voronoi diagram. A worst-case O(n log n) algorithm for points and segments is given by Fortune, A sweepline algorithm for Voronoi diagrams, SoCG'86. Held published the software package Vroni with an expected O(n log n) time complexity, which actually computes the maximum inscribed circle, too. And there seems to be an implementation in boost, too.
For simple polygons (i.e., without holes) a time-optimal algorithm that runs in O(n) time is due to Chin et al., Finding the Medial Axis of a Simple Polygon in Linear Time, 1999.
Brute force.
However, as you stated that you are fine with a brute-force algorithm: What about simply trying out all triplets of sites (vertices and edges). For each triplet you find candidate Voronoi nodes, i.e., equidistant loci to the three sites and check whether any other site would intersect the candidate maximum inscribed circle. If there is an intersection you dismiss the candidate. Take the greatest you can find over all triplets.
See chapter 3 in my Master thesis about more details on computing equidistant loci for three sites.
I implemented a piece of python code based on cv2 to get the maximum/largest inscribed circle inside mask/polygon/contours. It supports non-convex/hollow shape.
import cv2
import numpy as np
def get_test_mask():
# Create an image
r = 100
mask = np.zeros((4 * r, 4 * r), dtype=np.uint8)
# Create a sequence of points to make a contour
vert = [None] * 6
vert[0] = (3 * r // 2, int(1.34 * r))
vert[1] = (1 * r, 2 * r)
vert[2] = (3 * r // 2, int(2.866 * r))
vert[3] = (5 * r // 2, int(2.866 * r))
vert[4] = (3 * r, 2 * r)
vert[5] = (5 * r // 2, int(1.34 * r))
# Draw it in mask
for i in range(6):
cv2.line(mask, vert[i], vert[(i + 1) % 6], (255), 63)
return mask
mask = get_test_mask()
"""
Get the maximum/largest inscribed circle inside mask/polygon/contours.
Support non-convex/hollow shape
"""
dist_map = cv2.distanceTransform(mask, cv2.DIST_L2, cv2.DIST_MASK_PRECISE)
_, radius, _, center = cv2.minMaxLoc(dist_map)
result = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
cv2.circle(result, tuple(center), int(radius), (0, 0, 255), 2, cv2.LINE_8, 0)
# minEnclosingCircle directly by cv2
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]
center2, radius2 = cv2.minEnclosingCircle(np.concatenate(contours, 0))
cv2.circle(result, (int(center2[0]), int(center2[1])), int(radius2), (0, 255, 0,), 2)
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)
Red circle is max inscribed circle
Source: https://gist.github.com/DIYer22/f82dc329b27c2766b21bec4a563703cc
I used Straight Skeletons to place an image inside a polygon with three steps:
Find the straight skeleton using the Straight Skeleton algorithm (pic 1)
Base on the straight skeleton, find the largest circle (pic 2)
Draw the image inside that circle (pic 3)
Try it at: https://smartdiagram.com/simple-infographics-3d-charts-2/
An O(n log X) algorithm, where X depends on the precision you want.
Binary search for largest radius R for a circle:
At each iteration, for a given radius r, push each edge E, "inward" by R, to get E'. For each edge E', define half-plane H as the set of all points "inside" the the polygon (using E' as the boundary). Now, compute the intersection of all these half-planes E', which could be done in O(n) time. If the intersection is non-empty, then if you draw a circle with radius r using any point in the intersection as the center, it will be inside the given polygon.