Sign in to follow this  
Scythen

How to map a triangle to a circle?

Recommended Posts

If I have an equilateral triangle and its circumcircle is there some way I can map any point in the circle to a point on the triangle? Equilateral triangle with Circumcircle This may not make much sense but what I want to do is make a gauge like the foot gauge in DDR Max but I don’t want the lines. The result would be that any point on the edge of the triangle would map to a point on the circumference of the circle and points inside the triangle would map to points inside the circle. The center of the triangle would map precisely to the center of the circle. Id also like to be able to determine where a point on the circle mapped to the triangle. I hope I explained that well, it’s sounds confusing when I read it [headshake]

Share this post


Link to post
Share on other sites
Yeah, the description is a little confusing but it doesn't sound like an easy thing to describe. :)

I guess the easiest way to figure it out is to ask which shape is your input and which is your output?

Like, do you have a point on a triangle that you want to place on the sphere or vice-versa?

Share this post


Link to post
Share on other sites
Quote:
Original post by Scythen
Id also like to be able to determine where a point on the circle mapped to the triangle.

You could create a linear mapping for that:

You've got 3 points (A,B,C), 3 wedges of the circle (1,2,3) and 3 lines (AB,BC,CA).

A
3 / \ 1
C---B
2

Let's say A is at angle 0º, B is at 120º and C is at 240º.

Find the angle of your arbitrary point, I'll call this O.


assert( O >= 0 && O < 360 )
if( O < 120 ) //point is in wedge 1
{
fr = O/120;
Pt = fr * B + (1-fr) * A;
}
else if( O < 240 )//point is in wedge 2
{
fr = (O-120)/120;
Pt = fr * C + (1-fr) * B;
}
else //( O < 360) //point is in wedge 3
{
fr = (O-240)/120;
Pt = fr * A + (1-fr) * C;
}



Share this post


Link to post
Share on other sites
I'm reading through this in a bit of a rush so I'm not entirely sure on what your desired application is. But you can certainly uniquely map a point on a triangle to a point on a circle (or vice versa).

I'd take a point at the centre of the triangle and map it to the centre of the circle, like you've done in your diagram. Then you need to stretch each ray from the centre to the end of the triangle out to the radius of the circle. I'd probably use a polar coordinate system for the circle, and map the triangle to something similar. You'll need to calculate the length of the line segment from the centre of the triangle to the edge, which you can do given an polar angle by using some trig and the right angle triangles you can contruct using the shortest distance from the centre of the triangle to the edges.

I know that's probably really confusing without a diagram, so I might have to scribble something once I'm at home and have my scanner (and more time).

Share this post


Link to post
Share on other sites
Assuming you want the edge of the triangle to map to the edge of the circle, and points within the triangle to 'blow out' linearly, I think this is quite easy. At the three 'vertex angles' (0, 120, 240 degrees), the mapping is 1:1. At the three 'centre angles' (60, 180, 300 degrees), the mapping is 2:1 (the edge of the triangle is half the distance from the centre that the edge of the circle is). Interpolating linearly between these expansion values (1 and 2) for angles in between (i.e. 45 degrees is 45/60 of the way between 0 and 60, so it has a value (15/60)*1+(45/60)*2 = 1.75) will give you a factor you can use to increase the radius.

Share this post


Link to post
Share on other sites
Thanks for all the replies, even with my poor explanation it seems I got the point across.

Trapper Zoid,
Sounds interesting but I'm not sure I understand it exactly.

Bob Janova, Hodgman,
I think your ideas are closest to what I’m looking for. If I understand your explanation correctly what you’re saying is to find the angle to the point in the triangle that I want to map ‘blow out’ linearly then using that angle find the amount to shift the point outwards. To map the point back to the triangle use the same equation and linearly interpolate the point back toward the center.

PlayfulPuppy,
I have a point on a triangle that needs to be mapped to the circle and I need to go the other way as well.

Thanks everyone!

Share this post


Link to post
Share on other sites
Here's an outline of how I would implement the mapping from a triangle to a circle. (I assume you can work out the reverse from it, but let me know if that's not obvious).



In this diagram, O is the origin (centre of circle and of triangle), and P is the point (x_p, y_p), inside the triangle that you want to map to the circle. The original point within the triangle and the mapped point within the circle should lie on the dotted line.

Firstly, find the gradient of the line OP, which is y_p/x_p.
The equation of the line is therefore y = (y_p/x_p)x.

For each of the three sides of the triangle:
-Calculate the gradient of the line m_s = (y2 - y1)/(x2 - x1) where (x1, y1) and (x2, y2) are the coordinates of the end points of the line (vertices of the triangle). It doesn't matter which point is chosen as which. Its equation is then y-y_1 = m_s(x-x_1).
-Substitute the equation of the line OP into the equation of the line of the triangle side (AB/BC/AC) to find the point of intersection, which should give you:
(y_p/x_p)x-y_1 = m_s(x-x_1)

This can be solved to give:
x = (y1-m_s*x1)/(y_p/x_p-m_s)
y = (y1-m_s*y1)/(1-m_s/y_p)

(You may want to check the maths on that however.)

You should now have three points of intersection. Calculate the distance from the origin [sqrt(x^2 + y^2)] for all of them, and choose the closest point.

Now, the point within the triangle gets mapped to the circle by scaling it by a variable factor. This factor can simply be calculated as r / sqrt(x^2 + y^2), where r is the radius of the circle. Multiply the x and y coordinates of the original point by this factor and you should have your mapped point.

There are probably easier ways to do all this, but hopefully this method will work for you. :)

Share this post


Link to post
Share on other sites
After rethinking this I'm not sure but it looks like alex_myrpg has the only solution that works.

I thought that Bob Janova had it but when I think about the linear interpolation I don’t see how that will result in a curve. Using just points that lay on the edge of the triangle the resulting points will be in straight lines between the corner of the triangle, the center of the edge projected to the circle and the second corner. The factor used to multiply with can’t be linear. Hodgman has the same problem.

Am I wrong?

So, I still haven’t worked it out but I think alex_myrpg is on to it.

[Edited by - Scythen on March 21, 2008 10:46:25 AM]

Share this post


Link to post
Share on other sites
Hmm, you're right, my version will produce a hexagon. However, there is a straight line in the problem: the triangle itself. So try interpolating between 1 and 0.5, and then taking the reciprocal.

Share this post


Link to post
Share on other sites
Bob Janova - I'm not quite sure what method you're getting at, but I'm fairly sure this problem involves finding the distance from a point to a line somewhere. Perhaps I am just missing a simpler way of doing this, however...

Scythen - let me know how well your implementation of my method works. Note that several of the values used in the calculations can be predetermined and stored (e.g. gradients of triangle sides), so the algorithm should not really be that computationally intensive. Still, perhaps you can simplify it a bit further.

Share this post


Link to post
Share on other sites
Ok, I've made some progress!

I used the cos between O-P and the midperpendicular to get the base scale factor for the final point. Here is the code that maps the point correctly (I think) to the circle.


Vector2 MapPointOnEquilateralTriangleToCircle(Vector2 P)
{
float angle = Angle(new Vector2(0, 1), P);

angle *= 180.0f / (float)Math.PI;
if (angle < 0)
angle += 360.0f;

float cos;
if (angle <= 120)
cos = (float)Math.Cos(Angle(nrmAB, P));
else if (angle <= 240)
cos = (float)Math.Cos(Angle(nrmBC, P));
else
cos = (float)Math.Cos(Angle(nrmCA, P));

float f = 1 - (2 * (1 - cos));

Vector2 n = new Vector2(P);
float len = n.Normalize();
return P + (n * f * len);
}


EDIT: removed code that did not work

[Edited by - Scythen on March 21, 2008 5:31:39 PM]

Share this post


Link to post
Share on other sites
Ok, while mapping the point from the triangle to the circle is fine going the other way is not.

My test app is here test app if anyone cares to look.

Maybe some sleep will help [dead]

Share this post


Link to post
Share on other sites
I think there's an easier / simpler / quicker way....
using just vector math, rather than trig, angles or y=mx+c ... ick!!

Normalise P into a Unit vector N
Then take the Dot product with a unit vector which is "normal" to one of the sides.
If the result is < 0.5, try again with a different side,
If the result is still < 0.5, the point must be "near" the 3rd side

I've tried to stick with your notation...
I've assumed the nrmAB, nrmBC and nrmCA are outward facing Unit Vectors..
and you've got Dot available.

Vector2 MapPointOnEquilateralTriangleToCircle(Vector2 P)
{ Vector2 n = new Vector2(P);
float len = n.Normalize();
float dp = n.Dot(nrmAB);
if (dp < 0.5) {
dp = n.Dot(nrmBC));
if (dp < 0.5) dp = n.Dot(nrmCA);
}
float f = dp * 2;
// Optional - ensure output point is not outside circle
// if ( f*len > Radius ) f = radius / len;
return P * f;
}




The Circle2Triangle routine is identical except, the last few lines

Vector2 MapPointOnCircletoEquilateralTriangle(Vector2 P)
{ Vector2 n = new Vector2(P);
float len = n.Normalize();
float dp = n.Dot(nrmAB);
if (dp < 0.5) {
dp = n.Dot(nrmBC));
if (dp < 0.5) dp = n.Dot(nrmCA);
}
float f = dp * 2;

// Optional - ensure output point is not outside the triangle
// if ( len > Radius ) f = f * len / radius;
return P / f;
}




HTH

[Edited by - daftasbrush on March 22, 2008 5:55:49 AM]

Share this post


Link to post
Share on other sites
I didn't fully understand all the methods posted so I apologize if this has already been posted, but here's what I would do. Construct a ray from the center(o) to the point(p). Intersect that ray with the triangle(t)(3 line to line collisions) and the circle(c)(c=o+(p-o)*(r/|p-o|). If converting from the triangle to the to the circle the new point is n=o+(p-o)*|c-o|/|t-o| . If converting from the circle to the triangle the new point is n=o+(p-o)*|t-o|/|c-o|.

Share this post


Link to post
Share on other sites
so much math for what sounds like a simple answer. a point around the circle mapped to a point around a triangle, and then the opposite??? it's all about ratios. If you are finding a point 2/5th's around the circle then just find the same point along the triangle sides. It's like a race track... side 1 then side 2 then side 3 takes you all the way back to the start, as does following the circumference of the circle. if you know how long each side of the triangle is then just figure-out how far along you've travelled around the circle and map that to the triangle.

in terms of points within the circle mapping to the triangle, then i'd be looking at what angle it is in the circle, and then taking into account how long each side is and figuring-out ...... no lets go with an example...

let's say that the triangle has sides 10 units long, 5 units long, and 5 units long again... obviously the 10 units long side takes-up 50% of the total distance 'around' the triangle track... therefore if the angle in the circle is within the first 50% of it's circumference then i'd be mapping how far in that 50% of the circle you are finding to the same point along the triangles first side of 10 units long... and then you just need to find the ratio between how far the point is to the circumference and map that to the distance from the triangle centre to the point you calculated along the first side just before.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this