I'm calculating shortest path of a robot on a plane with polygonal obstacles. Everything works well and fast, no problems there. But, how to smoothen the path so it becomes curvy ?
Below is a picture of a path connecting vertices with a straight line.
P.S
Robot is just a circle.
This paper might be useful. It looks like it's a non-trivial problem. Abstract:
Automatic graph drawers need to compute paths among ver- tices of a simple polygon which besides remaining in the interior need to exhibit certain aesthetic properties. Some of these require the incorpo- ration of some information about the polygonal shape without being too far from the actual shortest path. We present an algorithm to compute a locally convex region that “contains” the shortest Euclidean path among two vertices of a simple polygon. The region has a boundary shape that “follows” the shortest path shape. A cubic Bezier spline in the region in- terior provides a “short and smooth” collision free curve between the two given vertices. The obtained results appear to be aesthetically pleasant and the methods used may be of independent interest. They are elemen- tary and implementable. Figure 7 is a sample output produced by our current implementation.
I used to play with path calculation techniques a lot when trying to make realistic flying sequences to be rendered in Teragen. I initially tried using Bézier Curves.
But discovered that (for flying at least) they aren't that useful. The reason is that the curvature between curves is discontinuous, and so cannot be used to calculate a continuous correct banking angle for a fly-by. Also, it's hard to be sure that the curve doesn't intersect an mountain.
I digress. The way I eventually settled on was a simple mass-spring based path, and relax it into submission.
Subdivide the path into lots of little segments, the more the merrier. For each point, move it a little bit in a direction so as to reduce the angle between it and its neighbours, and way from the obstacles. Repeat many times until the path has settled down.
k = 0.01 // Adjust the values of k and j to your liking.
j = 0.01 // Small values take longer to settle. Larger values are unstable.
For each point P
normal_vector = vector_to_previous_point + vector_to_next_point
obstacle_vector = vector_to_nearest_obstacle
obstacle_distance = magnitude(obstacle_vector)
obstacle_vector *= obstacle_distance^2
P += (normal_vector * k) - (obstacle_vector * j)
The benefit of these kind of finite element relaxation techniques is that you can program all kinds of constraints into it, and the path will settle on some compromise between them, depending on the weights (j and k in this case).
If you're into robotics, why not come and join the Robotics Proposal?
Can't you just make the path curvy in the actual execution of the path following algorithm? If you leave the path as is (i.e. connected straight lines), implementing a look ahead distance of ~1 meter (this value will depend on the speed of your robot and the amount you've padded the configuration space to avoid obstacles) in the control algorithm that calculates the velocity of each wheel will automatically smooth out the path without any need for preprocessing.
Here's a quick images of what I mean...the red dotted-line is the path that is actually executed by the robot when you control to a point based on a lookahead distance. A lookahead distance just computes a point further down the path by some arbitrary distance.
Again, the only thing you have to worry about is how much you're padding obstacles to make sure you avoid hitting them. Normally I believe the area of an obstacle is padded by half the robot's radius, but if you're controlling to a lookahead distance you may have to make this slightly larger.
In the case of a robot we can't know the future. We have to draw each point knowing only the location of the robot and the obstacles. The usual method for making curved paths of minimum length is to model the robot with a circle and move the circle so it remains in contact with the obstacles. Just keep one radius away and the turns will be curves.
If you want curves and NOT minimum distance try making the above radius proportional to the distance you are from a polygon vertex.
The Bezier curves idea only works to make the path curved in retrospect. It changes where the robot ha been. Usually with robots changing the past is called "cheating". One way to avoid having to change the path you've already walked is to look ahead. But can the robot see around corners? You have to specify the rules better.
Related
Please see the image below.
This path object is created using 4 Bezier curve on each side.
Currently I am facing a problem when I try to get bounds of this path object created using cubic brazier curves. As you can see top and bottom sides have control point away from the curve which makes bounds totally inaccurate.
So my question is is it possible to create a jigsaw puzzle piece like in the image having all control points on or at the level of the curve. ( That is creating a curve and perfect mirror of it, all points within the bounds of the curve)
Don't calculate the bounds by using the control points, then. At least if you need tight bounds and don't want a quick check for potential visibility in a given clipping rectangle.
This awesome site can help a lot with common Bézier curve calculations, including bounding box.
Alternatively, switch to splines where the control points are on the curve, but then you could end up with the opposite effect where the curve extends beyond the bounds imposed by its control points.
You can easily convert your BEZIER cubic control points into Interpolation cubic. Just by reversing this:
BEZIER vs. interpolation cubic
so:
/* bezier = interpol
1 | ( x0)=X1;
t | (3.0*x1)-(3.0*x0)=(0.5*(X2-X0));
tt | (3.0*x2)-(6.0*x1)+(3.0*x0)=(3.0*(X2-X1))-(X2-X0)-(0.5*(X3-X1));
ttt|( x3)-(3.0*x2)+(3.0*x1)-( x0)=(0.5*(X2-X0))+(0.5*(X3-X1))+(2.0*(-X2+X1));
1 | ( y0)=Y1;
t | (3.0*y1)-(3.0*y0)=(0.5*(Y2-Y0));
tt | (3.0*y2)-(6.0*y1)+(3.0*y0)=(3.0*(Y2-Y1))-(Y2-Y0)-(0.5*(Y3-Y1));
ttt|( y3)-(3.0*y2)+(3.0*y1)-( y0)=(0.5*(Y2-Y0))+(0.5*(Y3-Y1))+(2.0*(-Y2+Y1));
*/
// input: x0,y0,..x3,y3 ... Bezier control points
// output: X0,Y0,..X3,Y3 ... interpolation control points
double x0,y0,x1,y1,x2,y2,x3,y3,m=1.0/9.0;
X0=x0-(x1-x0)/m; Y0=y0-(y1-y0)/m;
X1=x0; Y1=y0;
X2=x3; Y2=y3;
X3=x3+(x3-x2)/m; Y3=y3+(y3-y2)/m;
Hope I did not make any algebraic mistake. This will move all control points into your curves directly while the shape will be unchanged. Beware that for BBOX computation you should only use (X1,Y1) and (X2,Y2) as the used parameter t=<0,1> is interpolating between them !!!.
But even this can provide inaccuracy as you can have some extremes without control point. In case even that is a problem (The BBOX is a bit smaller than should) you can re-sample your shape to set of points (for example 10 per cubic) on the curve with some step (0.1) and do the BBOX from those points. That will be much more precise but slower of coarse...
One property of Bezier curves is that as you split them, the distance between the smooth curve and the CVs shrinks.
So, one way to fix those CVs on the top and bottom is to split the related Bezier into two Beziers using the De Casteljau algorithm.
You could even do this algorithmically:
Find tight bounding box and CV-based bounding box.
If the difference is greater than your tolerance, find the max/min CVs and their related Bezier curves
Split all of the related Bezier curves into two Bezier curves each
Repeat
Eventually you'll hit your tolerance. You might have a lot of Beziers by then though if you have a very tight tolerance or tricky data.
I'm currently working on my master's thesis where I get:
A Delaunay triangulation drawn for me with given n points in (x, y, z) form.
My task is to use this triangulation and make contour lines at given z values.
I have been nearly successful at doing this by implementing the wikipedia spline interpolation : https://en.wikipedia.org/wiki/Spline_interpolation
My problem is that I get contour lines crossing each other when implementing the splines while of course the linear drawings doesn't cross.
Parametric cubic spline interpolated contour lines
If you look at the bottom part of the screen you see two contour lines crossing, I don't have enough reputation points to show that the linear drawings doesn't. You can also see that from point to point that the edges are way too rounded.
What I've tried is to interpolate more points between any pair of points to make more knot points along the lines, this to restrict them further, but to get non-crossing lines the splines look too much like a linear drawing which isn't satisfactory to the eye.
What I'd like to know, is not actual code implementation of the how, but maybe a pointer to how, readings and so forth.
(NB, I'm going to make this from scratch, no libraries).
Question: How to make a higher degree polynomial function which doesn't curve too much outside its linear counterpart. By too much I mean that a given contour at let's say 50 meters, that it doesn't cross a contour at 60 meters.
Any help is highly appreciated.
You can try a weighted delaunay triangulation. It's defined as the euklidian distance minus the weight.
Couples of years ago I solved similar task.
Here are some of my working notes. Probably it would help you.
Refer to XoomCode AcidMaps plugin, on github:
https://github.com/XoomCode/AcidMaps/tree/master/examples/isolines
Here is a demo:
http://ams.xoomcode.com/flex/index.html
Set, for example, the renderer type "Sparse" and interpolation strategy as "Linear", then press the "Update" button.
Refer to VividSolutions JTS Java library:
http://www.vividsolutions.com/jts/download.htm
http://mike.teczno.com/notes/curves-through-points.html
http://blog.csdn.net/xsolver/article/details/8913390
I'm trying to draw a flat surface out of voxels, the goal is to draw it filled and I'm having a lot of trouble. Everything I try results in holes on the surface. The surface has 4 corners, but I'd like to be able to use the same method for triangles too.
Here's what I've tried:
Draw along from one parallel side to the other
Draw only in one direction (z direction) along a side of the plane
I've had the most success with 2 but it fails when I add any pitch or roll to the plane (any elevation present).
Any tips? There's no code because I'm sure my implementations are all correct, it's just the choice of algorithm that's wrong.
EDIT:
On a side note, though number 2 had less holes, the planes were distorted and didn't appear flat.
EDIT2:
I'm sticking with my first decision, but now the question is, how do I detect when there will be a hole? By observation I notice there's the same amount of holes per plane regardless of pitch and roll. Yaw is the culprit here.
EDIT3:
I'm leaving this question up but I decided to just test a nearby block to see if it's empty. I didn't want to do it, but yeah. If you have a more elegant solution I'm all ears.
A plane, being infinite, does not have corners. Are you talking about a four-sided polygon? Does it have square corners?
For a polygon, I would certainly start off with a triangle, since you can construct any other polygon out of triangles, not the other way around.
Then, a good start for filling a triangle would probably be to come up with an accurate test of whether a given voxel should be filled or not. Here's an example of two different point-in-triangle tests.
After you have that you can proceed in different ways. For example, although not the most efficient, you could region-grow from the center, testing each neighboring voxel and recursing with a stack.
i want to find a circular object(Iris of eye, i have used Haar Cascase with viola Jones algorithm). so i found that hough circle would be the correct way to do it. can anybody explain me how to implement Hough circle in Java or any other easy implementation to find iris with Java.
Thanks,
Duda and Hart (1971) has a pretty clear explanation of the Hough transform and a worked example. It's not difficult to produce an implementation directly from that paper, so it's a good place for you to start.
ImageJ provides a Hough Circle plugin. I've been playing around with it several times in the past.
You could take a look at the source code if you want or need to modify it.
If you want to find an iris you should be straightforward about this. The part of the iris you are after is actually called a limbus. Also note that the contrast of the limbus is much lower than the one of the pupil so if image resolution permits pupil is a better target. Java is not a good option as programming language here since 1. It is slow while processing is intense; 2. Since classic Hough circle requires 3D accumulator and Java probably means using a cell phone the memory requirements will be tough.
What you can do is to use a fact that there is probably a single (or only a few) Limbuses in the image. First thing to do is to reduce the dimensionality of the problem from 3 to 2 by using oriented edges: extract horizontal and vertical edges that together represent edge orientation (they can be considered as horizontal and vertical components of edge vector). The simple idea is that the dominant intersection of edge vectors is the center of your limbus. To find the intersection you only need two oriented edges instead of three points that define a circle. Hence dimensionality reduction from 3 to 2.
You also don’t need to use a classical Hough circle transform with a huge accumulator and numerous calculations to find this intersection. A Randomized Hough will be much faster. Here is how it works (~ to RANSAC): you select a minimum number of oriented edges at random (in your case 2), find the intersection, then find all the edges that intersect at approximately the same location. These are inliers. You just iterate 10-30 times choosing a different random sample of 2 edges to settle in a set with maximum number of inliers. Hopefully, these inliers lie on the limbus. The median of inlier ray intersections will give you the center of the circle and the median distance to the inliers from the center is the radius.
In the picture below bright colors correspond to inliers and orientation is shown with little line segment. The set of original edges is shown in the middle (horizontal only). While original edges lie along an ellipse, Hough edges were transformed by an Affine transform to make those belonging to limbus to lie on a circle. Also note that edge orientations are pretty noisy.
I need to generate a Voronoi diagram around a concave (non-convex) inside polygon. I have looked for methods online, but I haven't been able to figure out how to do this. Basically, I generate the convex hull of the points, calculate the dual points and build an edge network between these points. However, when meeting the edges of the inside polygon, it has to look like the edge of the shape, just like the convex hull. So, by doing this and clipping all the edges at the borders, I should end up with a Voronoi diagram that has nice edges to the borders of the inside polygon and no cells that are on both sides of the inside polygon.
Let me give you an example:
The problem with this is that the cells cross the inside polygon edges and there is no visual relation between the cell structure and the polygon shape.
Does anybody know how to approach this problem? Is there some algorithm that already does this or gets close to what I'm trying to achieve?
Thank you so much for any kind of input!
You might be able to build a conforming Delaunay triangulation (i.e. a triangulation that includes the polygon edges as constraints) and then form the Voronoi diagram as the dual. A conforming triangulation will ensure that no edge in the triangulation intersects with a constraint edge - all constraint edges will be an edge in the triangulation.
Have a look at the Triangle package here, as a reference for this type of approach. In my experience it's a fast and robust library, although it's written in c not java.
I'm not sure I understand at this stage how the points (the Voronoi centres) are generated in your diagram. If you're actually looking to do mesh generation in a polygonal domain, then there may be other approaches to consider, although the Triangle package supports (conforming) Delaunay refinement mesh generation.
EDIT: It looks like you can also directly form the Voronoi diagram for general line segments, check out the VRONI library, here. Addressing your comment - I'm not sure that you can always expect to have a uniform Voronoi diagram that also conforms to a general polygonal boundary. I would expect that the shape of the polygonal boundary would impose a maximum dimension on the boundary Voronoi cells.
Hope this helps.
Clearly you need to generate your Voronoi diagram to the constraints of the greater polygon. Although you refer to it as a polygon, I notice that your example diagram has spline-based edges. Let's forget that for now.
What you want to do is to ensure that you start out with the containing polygon (whether generated by you or from another source) having edges of fairly equal length; a variance factor would make this look more natural. I would probably go for a variance of 10-20%.
Now that you have your containing polygon bounded by lines segments of approximately equal length, you have a basis from which to begin generating your Voronoi diagram. For each edge on your container:
Determine the edge normal (perp line jutting inward from centre of that segment).
Use the edge normal as a sliding scale on which to place a new Voronoi node centre. The distance away from the edge itself would be determined by what you want your average Voronoi cell "diameter" to be, if they were all taken as circles. In your example that looks like maybe 30 pixels (or whatever the equivalent in your world units would be). Again, you should apply a variance factor to this so that not every cell centre is placed equidistant from its source edge.
Generate the Voronoi cell for your newly placed centre.
Store your Voronoi cell source point in a list.
As you incrementally generate each point, you should begin to see that the algorithm subdivides each convex "constituent area" of your concave container in a radial fashion.
You may be wondering what the list is for. Well, obviously, you're not done yet, you've only generated a fraction of the total Voronoi tesselation you want. Once you have created these "boundary" cells of your concave space, you don't want new cells to be generated closer to the boundary than the boundary cells already are, you only want them inside that area. By maintaining a list of the boundary cell source points, you can then ensure that any further points you create are inside that area. It's a little bit like taking an internal Minkowski sum to ensure you have a buffer zone. Now you can randomise the rest of your cells in this derived concave space, to completion.
(Caveat emptor: You will have to be careful with this previous step. If any "passage" areas are too narrow, then the boundaries of this derived space will overlap, you will have a non-simple polygon, and you may find yourself placing points in the wrong places in spite of your efforts. The solution is to ensure that either your maximum placement distance from edges is never more than half of your minimum passage width... or use some other geometric means, including Minkowski summation as one possibility, to ensure you do not wind up with a degenerate derived polygon. It is quite possible that you will end with a multipolygon, i.e. fragments.)
I've not applied this method myself yet, but although there will certainly be bugs to work out, I think the general idea will get you started in the right direction.
Look for a paper called:
"Efficient computation of continuous skeletons" by Kirkpatrick, David G, written in 1979.
Here's the abstract:
An O(n lgn) algorithm is presented for the construction of skeletons
of arbitrary n-line polygonal figures. This algorithm is based on an
O(n lgn) algorithm for the construction of generalized Voronoi
diagrams (our generalization replaces point sets by sets of line
segments constrained to intersect only at end points). The generalized
Voronoi diagram algorithm employs a linear time algorithm for the
merging of two arbitrary (standard) Voronoi diagrams.
"Sets of line segments is the constrained to intersect only at end points" is the concave polygon you describe.