views:

323

answers:

3

Given the image below

1. I have updated the image based on feedback from Steven_W so there are 4 triangles in the right hand diagram instead of 3 which makes more sense!

2. update image again to label sub triangles as A, B, C, D in grey

Mapping diagram

What is the pseudo algorithm for mapping a coordinate (x,y) in the left hand square such that a coordinate (u,v) is produced within the rectangle bounding the triangle on the right so that points are interpolated between the mapping points as illustrated on the diagram?

1 to 4 are equidistant on the triangle from left to right even though my illustration is a bit rough around the edges :)

This is to generate a rough and ready panel for the lid of a skybox from the top half a 360 degree panoramic photo.

update 3 based on feedback

The first step appears to be working out which triangle we are in for the left hand diagram based on the (x,y) coordinates.

The second steep is to work out the distance along the vertices of that triangle. Then use those distances to get the coordinates on the related triangle in the diagram on the right

update 4 - code to identify triangle in left hand diagram

Public Function TriangleIndex(ByVal x As Integer, ByVal y As Integer, ByVal w as integer, ByVal h as integer) as integer                              
    Dim AboveForwardSlashDiagonal As Boolean = ((((h * x) + (w * y)) - (h * w)) < 0)
    Dim AboveBackSlashDiagonal As Boolean = (((h * x) - (w * y)) > 0)
    If AboveForwardSlashDiagonal Then
         If AboveBackSlashDiagonal
            return 2 ' C
         else
            return 3 ' D
         end if
    else
         If AboveBackSlashDiagonal
            return 1 ' B
         else
            return 0 ' A
         end if
    End If
End Function

update 5 - template for code solution

w1 and h1 are dimensions of left diagram w2 and h2 are dimensions of right diagram

Private Function TranslateToTriangle(ByVal x1 As Integer, ByVal y1 As Integer, ByVal w1 As Integer, ByVal h1 As Integer, ByVal w2 As Integer, ByVal h2 As Integer) As System.Drawing.Point

    Dim ReturnPoint As New System.Drawing.Point


        select case TriangleIndex(x1,y1,w1,h1)
            case 0

            case 1

            case 2

            case 3

        end select

    Return ReturnPoint

End Function

update 6 formula for area of triangle given it's lengths - which might be helpful in calculating barycentric weights?

Private Function AreaOfTriangle(ByVal LengthA As Single, ByVal LengthB As Single, ByVal LengthC As Single) As Single
    Dim Perimeter As Single = LengthA + LengthB + LengthC
    Return 1 / 4 * Math.Sqrt(Perimeter * (Perimeter - 2 * LengthA) * (Perimeter - 2 * LengthB) * (Perimeter - 2 * LengthC))
End Function
+1  A: 

It is not really clear why certain points map to their counterpart on the triangle.

For example, where should a point map to that is equidistant between '1' and '4' ?

Or, a point just "above" number 5 ?

Steven_W
I'm splitting the panorama into 4 sections. Imagine you are inside a box facing forwards. The first 1/4 of the panorama image from left to right is used for the face of the box in front of you. the second 1/4 of the panorama from left to right is used for the cube face to the right of you. the next the panel behind you. and last the panel to the left of you. The lid which is the image on the left in the mapping diagram above. The numbers 1 to 4 represent the corners of the cube.
PeanutPower
Oh-kaaay, I can get that. Why are you then mapping to a triangle? What is the triangle for?
Chris
You seem to be trying to map 4 triangles into 3. The square has 4 triangular regions: 5-1-2, 5-2-3, 5-3-4, 5-4-1, but the destination triangle is divided into only 3 triangular regions: 5-1-2, 5-2-3, 5-3-4 ?
Paul R
Sorry to admit, but I don't really understand what it is that you're trying to achieve or how this fits into a "panoramic" view.
Steven_W
Shouldn't the "resulting triangle" have "1-2-3-4-1" along the bottom ?
Steven_W
+1  A: 

Well, your comment to @Steven_W's answer makes the answer to your question clearer. You actually want to map points in the 4 triangles (125, 235, 435, 415) in your square box to the corresponding 4 triangles in your other square box (125, 235, 435, 415). Oh, you don't have triangle 415 in your second box, perhaps you should or maybe not.

So now you have to map points from triangle to triangle which should be easy. As coordinates for each point in your 'start' triangle use its position relative to all 3 vertices, then use the same position relative to the 3 vertices of the 'destination' triangle. You could probably get away with using just 2 of the triangle vertices for coordinates.

HTH

The Wikipedia entry trilinear coordinates explains the maths well enough I think.

High Performance Mark
So basically work out which triangle I am in in the left hand diagram. Then work out the distance along the vertices of that triangle. Then use the distances to get the coordinates on the related triangle in the diagram on the right?
PeanutPower
Basically, yes, but check the Wikipedia page I referenced, much clearer than I ever manage.
High Performance Mark
+1  A: 

Let's consider first the case of the triangle a.

Assuming that your origin is at point 5, the coordinates of points 1 and 2 are (-x0, y0) and (x0, y0), we should have the following.

The mapping from the old coordinates (x, y) into new (xnew, ynew) must be linear. This means, we've got the following formulae with still undefined coefficients:

xnew = A*x + B*y + C
ynew = D*x + E*y + F

How can we determine the coefficients? We've got three pairs of values: (-x0, y0) -> (-x0, y0), (x0, y0) -> (-x0/2, y0) and (0, 0) -> (0, -y0). This gives us the following:

-x0 = -A*x0 + B*y0 + C   (1)        -x0/2 = A*x0 + B*y0 + C   (3)
 y0 = -D*x0 + E*y0 + F   (2)         y0   = D*x0 + E*y0 + F   (4)

  0 =  A*0  + B*0  + C   (5)
-y0 =  D*0  + E*0  + F   (6)

Good so far. (5) gives us C = 0, (6) gives F = -y0. Adding (2) and (4) we get 2*y0 = 2*E*y0 + 2*(-y0), hence E = 2. Subtracting (2) and (4) we get 0 = 2*D*x0, hence D = 0. Adding (1) and (2) and taking into account that C = 0, we get -(3/4)*x0 = 2*B*y0, hence B = -3/4*x0/y0. Lastly, subtracting (1) and (2) we get x0/2 = 2*A*x0, hence A = 1/4.

Now, we can write down the needed mapping:

xnew = 0.25*x - 0.75*(x0/y0)*y
ynew = 2*y - y0

The same way, for triangle c we obtain:

xnew = -0.25*x - 0.25*(x0/y0)*y
ynew = -2*y - y0
Vlad
this is looking like a nice solution to part B but i'm not sure i totally understand the principle behind it?
PeanutPower
The principle is simple. For the case A, the code shrinks 4x the source triangle by `x` and moves it to the appropriate position, as well it stretches it by `y` 2x. Should be simple.
Vlad
hey i think you might have it and nice and clean too
PeanutPower
oops, my calculation was wrong. let's redo it.
Vlad