Advertisement

Arc calculation

Started by December 10, 2013 12:33 PM
9 comments, last by ferrous 11 years, 2 months ago

I'd like a user to be able to bend a line by dragging the end. The line will be an arc when bent. The length of the arc (L) needs to stay constant. The other end of the line, not being dragged, is at known point P1 and angle a1, which shouldn't change when the other end P2 is being dragged. The way I want it to work is that the angle at P2 (a2) should be such that that end of the line points towards the cursor when being dragged (Pc). The difficulty is that I can't work out P2 without knowing a2 and and I can't a2 without knowing P2. I have an expression where the only unknown is the radius r of the arc, but can't solve for it because of the complexity. I want to try to avoid numerical solutions. Has anyone done anything like this before? Is it possible to solve for r?

fn7eQOK.png

I'm not sure if this will produce the exact result you want, but you could think of this problem as equivalent to finding the circle (center position+radius) that passes through points P1 and P2 and is tangent to the line defined by P1,a1 (I *think* only one such circle will exist).

I don't have it in front of me, but the book "Geometric Tools for Computer Graphics" provides solutions for these sorts of problems (eg circle through 3 points, circles tangent to 2 lines, etc).

That circle should contain your desired arc, just start at P1 and move along the circle by your desired length.

Advertisement

EDIT: I think the formula is actually going to be the arc length of an ellipse, correct? As what will happen if the second point is dragged down to be next to the original point? Which, the formula for it's arclength is more complicated. It might be easier to have a bezier curve or something of that sort, or a minimum circle size, in which case, just use the formulas below for an arc + line?

I think numerical may be the only way to go: http://stackoverflow.com/questions/3152370/elliptical-arc-length

(Disregard all this)

Oh, I just did something like this, I think you're looking for something similar to this:

pinter_06.jpg

In which case, this article, at this page, might help:

http://www.gamasutra.com/view/feature/131505/toward_more_realistic_pathfinding.php?page=3

Basically, what you end up doing is:

It's two circles with a directional component (clockwise / CCW), that are centered at a radius distance away, 90 degrees to the left and right of the plane/object/whatever. You then try to find the tangent lines for each of those two circles to the destination point, normally you'd have two lines for each circle, but because each circle is rotating in only one direction, you end up only having one valid line per circle. To find that you form a right triangle from the center of the circle, the radius and the tangent point (which is the unknown) and solve for it.

You then end up taking the smallest arc length + smallest tangent line of the two circles (the left turning or the right turning circle) for the valid path.

You end up with something like Steambirds, if you drag around a destination node that the object tries to draw the shortest line to, given a turn radius.

(Though hmm, looks like I didn't notice that your R is an unknown, that certainly makes things more difficult.)

Thanks for your help. Raigan, P2 is unknown. Ferrous, yes r is unknown too. I've already played with Bezier curves but they require even more numerical solutions because the length is not constant. You need a numerical method to work out the length and another to move the control point until the length is the value you want.

I think the way I'll have to do it is to work out the endpoint P2 with no curvature (a1=a2), then work out the angle to the cursor (Pc) from P2, then work out P2 again, and repeat until it converges. I think it will converge quickly this way.

I've already done it a different way where a2 is calculated from Pc and the midpoint of the unbent line. The problem with this is that the cursor leaves P2 while dragging when the line is bent. When you go back to adjust P2 again it will jump to different position.

Edit: I've added an image to my post above.

Numeric solutions might still be not as bad as you think. Keep for example relaxation in mind, in case you are not satisfied with what analytic solutions you find.

Something like "bending" (with no particular mathematical notion such as it should be exactly a Bezier curve) can be implemented in a very straightforward way with a particle/spring system and 4-5 steps of relaxation.

Connect a number of points with fixed length constraints (there you have your constant arc length, each segment retains its length, thus the sum of all segments does as well). Then let the user drag the last point and run a few steps of relaxation. The other particles will follow by their constraints.

Now obviously, that alone will not cause the line to "bend", how to get that to happen? Apply a constant force orthogonal to the straight line's direction in the opposite direction the user is pulling on all particles (except the one the user is pulling). Now the position of the last particle is fixed by the user's pull, and it cannot go away any further as the sum of length constraints will allow it, and each particle in between will try to move towards the straight line, limited by its length constraint.

What you'll get is something that looks like a piece of rope that you lift on one end. A curve. And the nice thing is, you don't need to do any more calculations.

That sounds like a nice alternative Crossbones. Although I'll have to think carefully about how many particles there should be at different scales and also how to quickly draw the curves from the set of particles. I may need to draw hundreds of these curves per frames, so just drawing an arc may be the faster method.

Advertisement

how to quickly draw the curves from the set of particles

That's the nice bit about this technique. If you want to draw e.g. a Bezier curve given the user-dragged point and some other control points, you have to do extra work to calculate the curve.

If you want to draw the curve after having simulated those particles, you just connect the dots. They already form a curve.

how to quickly draw the curves from the set of particles

That's the nice bit about this technique. If you want to draw e.g. a Bezier curve given the user-dragged point and some other control points, you have to do extra work to calculate the curve.

If you want to draw the curve after having simulated those particles, you just connect the dots. They already form a curve.

They form an approximation to a curve. Drawing it requires multiple calls to a drawing function instead of just one for the arc.

I know I didn't mention this previously, but I also need to store the bent line in memory in a scalable and compact way. The arc lends itself to this much better.

Why are you trying to minimize the number of calls to drawing functions? Is that really a performance bottleneck in your program?

Yeah, you definitely have an ellipse, thinking about it more, you end up with an ellipse with one axis being the distance between the two points being dragged, and the other being the unknown, but based on arclength.

If for example, you take your picture up there, and assume P1 is r units away from C, what happens when you drag P1 to be r/10* units away from C?

*or any arbitrary number.

What is it you're really trying to do with this arc/line/curve?

This topic is closed to new replies.

Advertisement