# PureBasic Forum

 It is currently Thu May 23, 2013 7:19 pm

 All times are UTC + 1 hour

 Page 1 of 1 [ 9 posts ]
 Print view Previous topic | Next topic
Author Message
 Post subject: Calculate real 3D coordinates from 2DPosted: Mon Mar 26, 2012 9:30 pm

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 1716
I will have some 3D images of rectangle areas of the earth, and I will know the valid earth coordinates of the 4 corners. I am working to get additional information, for example the center of the given rectangle to know the perspective distortion, but first of all my general problem:
I want to calculate the earth coordinates from the screen coordinates, the altitude has to be ignored.

Code:
; Define

#W=640
#H=480

Global Dim Polygon(7)

Polygon(0)=40
Polygon(1)=40
Polygon(2)=340
Polygon(3)=30
Polygon(4)=550
Polygon(5)=300
Polygon(6)=100
Polygon(7)=440

Global Dim Real.f(7)

Real(0)=-100
Real(1)=-100
Real(2)=100
Real(3)=-100
Real(4)=100
Real(5)=100
Real(6)=-100
Real(7)=100

; EndDefine

Procedure.b IsPointInsideTriangle2D(x0.f,y0.f,x1.f,y1.f,x2.f,y2.f,px.f,py.f)

Protected V1x.f=x1-x0
Protected V1y.f=y1-y0
Protected V2x.f=x2-x1
Protected V2y.f=y2-y1
Protected V3x.f=x0-x2
Protected V3y.f=y0-y2

If V1y*(px-x0)>=V1x*(py-y0)
If V2y*(px-x1)>=V2x*(py-y1) And V3y*(px-x2)>=V3x*(py-y2)
ProcedureReturn #True
EndIf
Else
If V2y*(px-x1)<V2x*(py-y1) And V3y*(px-x2)<V3x*(py-y2)
ProcedureReturn #True
EndIf
EndIf

ProcedureReturn #False

EndProcedure

Procedure UpdateImage()

Protected x,y,color

x=WindowMouseX(0)
y=WindowMouseY(0)

StartDrawing(ImageOutput(0))
Box(0,0,#W,#H,#Black)

DrawingMode(#PB_2DDrawing_Transparent)
For i=0 To 3
LineXY(Polygon(i<<1&7),Polygon(i<<1&7+1),Polygon((i<<1+2)&7),Polygon((i<<1+3)&7),#White)
DrawText(Polygon(i<<1&7),Polygon(i<<1&7+1),Str(Real(i<<1&7))+"|"+Str(Real(i<<1&7+1)),#Blue)
Next i

LineXY((Polygon(0)+Polygon(6))>>1,(Polygon(1)+Polygon(7))>>1,(Polygon(2)+Polygon(4))>>1,(Polygon(3)+Polygon(5))>>1,#Gray)
LineXY((Polygon(0)+Polygon(2))>>1,(Polygon(1)+Polygon(3))>>1,(Polygon(6)+Polygon(4))>>1,(Polygon(7)+Polygon(5))>>1,#Gray)

color=#Red
If IsPointInsideTriangle2D(Polygon(0),Polygon(1),Polygon(2),Polygon(3),Polygon(4),Polygon(5),x,y)
color=#Green
EndIf
If IsPointInsideTriangle2D(Polygon(4),Polygon(5),Polygon(6),Polygon(7),Polygon(0),Polygon(1),x,y)
color=#Yellow
EndIf

LineXY(x-29,y,x+29,y,color)
LineXY(x,y-29,x,y+29,color)

; ============================
; x_ and y_ have to be calculated here...
; ============================
DrawText(x+10,y-25,Str(x_)+" | "+Str(y_),#Blue)

StopDrawing()

EndProcedure

OpenWindow(0,0,0,#W,#H,"")
CreateImage(0,#W,#H,24)
UpdateImage()

Repeat
Select WaitWindowEvent()
Case #WM_MOUSEMOVE
UpdateImage()
Case #WM_CHAR
End
EndSelect
ForEver

The above example only demonstrate the distorted rectangle and the "real" coordinates (-100|-100 to 100|100). The grey cross are drawn by using the median, but the center wouldn't be identical with the real center (0|0) because of the perspective. I am quite sure, I will also have the correct 2D coordinates of the center 0|0 (let's say, it will be 260|160 in the given example).

But how to calculate the earth coordinates when the mouse is within the rectangle?

Top

 Post subject: Re: Calculate real 3D coordinates from 2DPosted: Mon Mar 26, 2012 11:18 pm

Joined: Mon Jul 25, 2005 3:51 pm
Posts: 2401
Location: Utah, USA
Michael Vogel wrote:
But how to calculate the earth coordinates when the mouse is within the rectangle?

Use the intersection of two opposite corners of the earth rectangle.

Here's your code that is modified to show the center as an 'X':

Code:
; Define

#W=640
#H=480

Global Dim polygon(7)

polygon(0)=40
polygon(1)=40
polygon(2)=340
polygon(3)=30
polygon(4)=550
polygon(5)=300
polygon(6)=100
polygon(7)=440

Global Dim Real.f(7)

Real(0)=-100
Real(1)=-100
Real(2)=100
Real(3)=-100
Real(4)=100
Real(5)=100
Real(6)=-100
Real(7)=100

; EndDefine

Procedure.b IsPointInsideTriangle2D(x0.f,y0.f,x1.f,y1.f,x2.f,y2.f,px.f,py.f)

Protected V1x.f=x1-x0
Protected V1y.f=y1-y0
Protected V2x.f=x2-x1
Protected V2y.f=y2-y1
Protected V3x.f=x0-x2
Protected V3y.f=y0-y2

If V1y*(px-x0)>=V1x*(py-y0)
If V2y*(px-x1)>=V2x*(py-y1) And V3y*(px-x2)>=V3x*(py-y2)
ProcedureReturn #True
EndIf
Else
If V2y*(px-x1)<V2x*(py-y1) And V3y*(px-x2)<V3x*(py-y2)
ProcedureReturn #True
EndIf
EndIf

ProcedureReturn #False

EndProcedure

Structure POINT_f
x.f
y.f
EndStructure

Procedure rectangleCenterPoint(*center.POINT_f, *TL.POINT, *TR.POINT, *BR.POINT, *BL.POINT)
Protected dy1.f = *TL\y - *BR\y
Protected dy2.f = *TR\y - *BL\y
Protected dx1.f = *TL\x - *BR\x
Protected dx2.f = *TR\x - *BL\x

If dx1 = 0 Or dx2 = 0
;one of the sides is vertical, use this simplified formula instead
*center\x =  (*TR\x + *BR\x) / 2
*center\y =  (*TR\y + *BR\y) / 2
Else
Protected m1.f = dy1 / dx1
Protected m2.f = dy2 / dx2
Protected b1.f = *TL\y - m1 * *TL\x
Protected b2.f = *TR\y - m2 * *TR\x
*center\x = (b2 - b1) / (m1 - m2)
*center\y = m1 * *center\x + b1
EndIf
EndProcedure

Procedure UpdateImage()

Protected x,y,color

x=WindowMouseX(0)
y=WindowMouseY(0)

StartDrawing(ImageOutput(0))
Box(0,0,#W,#H,#Black)

DrawingMode(#PB_2DDrawing_Transparent)
For i=0 To 3
LineXY(polygon(i<<1&7),polygon(i<<1&7+1),polygon((i<<1+2)&7),polygon((i<<1+3)&7),#White)
DrawText(polygon(i<<1&7),polygon(i<<1&7+1),Str(Real(i<<1&7))+"|"+Str(Real(i<<1&7+1)),#Blue)
Next i

LineXY((polygon(0)+polygon(6))>>1,(polygon(1)+polygon(7))>>1,(polygon(2)+polygon(4))>>1,(polygon(3)+polygon(5))>>1,#Gray)
LineXY((polygon(0)+polygon(2))>>1,(polygon(1)+polygon(3))>>1,(polygon(6)+polygon(4))>>1,(polygon(7)+polygon(5))>>1,#Gray)

;draw actual center point
Protected center.POINT_f
rectangleCenterPoint(center, @polygon(0), @polygon(2), @polygon(4), @polygon(6))
LineXY(center\x - 5, center\y - 5, center\x + 5, center\y + 5, RGB(255, 255, 0))
LineXY(center\x + 5, center\y - 5, center\x - 5, center\y + 5, RGB(255, 255, 0))

color=#Red
If IsPointInsideTriangle2D(polygon(0),polygon(1),polygon(2),polygon(3),polygon(4),polygon(5),x,y)
color=#Green
EndIf
If IsPointInsideTriangle2D(polygon(4),polygon(5),polygon(6),polygon(7),polygon(0),polygon(1),x,y)
color=#Yellow
EndIf

LineXY(x-29,y,x+29,y,color)
LineXY(x,y-29,x,y+29,color)

; ============================
; x_ and y_ have to be calculated here...
; ============================
DrawText(x+10,y-25,Str(x_)+" | "+Str(y_),#Blue)

StopDrawing()

EndProcedure

OpenWindow(0,0,0,#W,#H,"")
CreateImage(0,#W,#H,24)
UpdateImage()

Repeat
Select WaitWindowEvent()
Case #WM_MOUSEMOVE
UpdateImage()
Case #WM_CHAR
End
EndSelect
ForEver

_________________

Top

 Post subject: Re: Calculate real 3D coordinates from 2DPosted: Tue Mar 27, 2012 6:37 am

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 1716
Hm,
your code calculates the center, but how to get the correct values for x_|y_ ?

I tried to use your center function to iterate the values, but failed. It's also not clear for me, how to calculate the appropriate centers of the four lines around the rectangle according to the calculated center...

Code:
; Define

#W=640
#H=480

Structure POINT_f
x.f
y.f
EndStructure

Global Dim Polygon(7)
Global Dim Real.f(7)

Global M.POINT_f
Global A.POINT_f
Global B.POINT_f
Global C.POINT_f
Global D.POINT_f

; EndDefine
Procedure InitValues()

Polygon(0)=40
Polygon(1)=40
Polygon(2)=340
Polygon(3)=30
Polygon(4)=550
Polygon(5)=300
Polygon(6)=100
Polygon(7)=440

Real(0)=-100
Real(1)=-100
Real(2)=100
Real(3)=-100
Real(4)=100
Real(5)=100
Real(6)=-100
Real(7)=100

EndProcedure
Procedure.i IsPointInsideTriangle2D(x0.f,y0.f,x1.f,y1.f,x2.f,y2.f,px.f,py.f)

Protected V1x.f=x1-x0
Protected V1y.f=y1-y0
Protected V2x.f=x2-x1
Protected V2y.f=y2-y1
Protected V3x.f=x0-x2
Protected V3y.f=y0-y2

If V1y*(px-x0)>=V1x*(py-y0)
If V2y*(px-x1)>=V2x*(py-y1) And V3y*(px-x2)>=V3x*(py-y2)
ProcedureReturn #True
EndIf
Else
If V2y*(px-x1)<V2x*(py-y1) And V3y*(px-x2)<V3x*(py-y2)
ProcedureReturn #True
EndIf
EndIf

ProcedureReturn #False

EndProcedure
Procedure.i IsPointInsideRectancle2D(x0.f,y0.f,x1.f,y1.f,x2.f,y2.f,x3.f,y3.f,x.f,y.f)

LineXY(x0,y0,x1,y1,RGB(80,80,80))
LineXY(x0,y0,x3,y3,RGB(80,80,80))
LineXY(x2,y2,x1,y1,RGB(80,80,80))
LineXY(x2,y2,x3,y3,RGB(80,80,80))

If IsPointInsideTriangle2D(x0,y0,x1,y1,x2,y2,x,y)
ProcedureReturn 1
EndIf
If IsPointInsideTriangle2D(x2,y2,x3,y3,x0,y0,x,y)
ProcedureReturn 2
EndIf

ProcedureReturn 0

EndProcedure
Procedure Cross(x,y,size,color)
LineXY(x-size,y-size,x+size,y+size,color)
LineXY(x+size,y-size,x-size,y+size,color)
EndProcedure
Procedure rectangleCenterPoint(*center.POINT_f, *TL.POINT, *TR.POINT, *BR.POINT, *BL.POINT)

Protected dy1.f = *TL\y - *BR\y
Protected dy2.f = *TR\y - *BL\y
Protected dx1.f = *TL\x - *BR\x
Protected dx2.f = *TR\x - *BL\x

If dx1 = 0 Or dx2 = 0
;one of the sides is vertical, use this simplified formula instead
*center\x =  (*TR\x + *BR\x) / 2
*center\y =  (*TR\y + *BR\y) / 2
Else
Protected m1.f = dy1 / dx1
Protected m2.f = dy2 / dx2
Protected b1.f = *TL\y - m1 * *TL\x
Protected b2.f = *TR\y - m2 * *TR\x
*center\x = (b2 - b1) / (m1 - m2)
*center\y = m1 * *center\x + b1
EndIf

EndProcedure
Procedure UpdateImage()

Protected x,y,color

x=WindowMouseX(0)
y=WindowMouseY(0)

InitValues()

StartDrawing(ImageOutput(0))
Box(0,0,#W,#H,#Black)

DrawingMode(#PB_2DDrawing_Transparent)
For i=0 To 3
LineXY(Polygon(i<<1&7),Polygon(i<<1&7+1),Polygon((i<<1+2)&7),Polygon((i<<1+3)&7),#White)
DrawText(Polygon(i<<1&7),Polygon(i<<1&7+1),Str(Real(i<<1&7))+"|"+Str(Real(i<<1&7+1)),#Blue)
Next i

LineXY((Polygon(0)+Polygon(6))>>1,(Polygon(1)+Polygon(7))>>1,(Polygon(2)+Polygon(4))>>1,(Polygon(3)+Polygon(5))>>1,#Gray)
LineXY((Polygon(0)+Polygon(2))>>1,(Polygon(1)+Polygon(3))>>1,(Polygon(6)+Polygon(4))>>1,(Polygon(7)+Polygon(5))>>1,#Gray)

Select IsPointInsideRectancle2D(Polygon(0),Polygon(1),Polygon(2),Polygon(3),Polygon(4),Polygon(5),Polygon(6),Polygon(7),x,y)
Case 0
color=#Red
Case 1
color=#Green
Case 2
color=#Yellow
EndSelect

LineXY(x-29,y,x+29,y,color)
LineXY(x,y-29,x,y+29,color)

; ============================
; x_ and y_ have to be calculated here...
; ============================

If color<>#Red

Protected iteration=10

While iteration
iteration-1

RectangleCenterPoint(M,@Polygon(0),@Polygon(2),@Polygon(4),@Polygon(6))
Cross(M\x,M\y,iteration,RGB(160,160,160))

RectangleCenterPoint(A,@Polygon(0),@Polygon(2),@Polygon(0),@Polygon(2))
RectangleCenterPoint(B,@Polygon(0),@Polygon(6),@Polygon(0),@Polygon(6))
RectangleCenterPoint(C,@Polygon(2),@Polygon(4),@Polygon(2),@Polygon(4))
RectangleCenterPoint(D,@Polygon(4),@Polygon(6),@Polygon(4),@Polygon(6))

If IsPointInsideRectancle2D(Polygon(0),Polygon(1),A\x,A\y,M\x,M\y,B\x,B\y,x,y)
Cross(A\x,A\y,2,RGB(160,160,160))
Cross(B\x,B\y,2,RGB(160,160,160))
Real(2)=(Real(0)+Real(2))/2
Real(3)=(Real(1)+Real(3))/2
Real(4)=(Real(0)+Real(2))/2
Real(5)=(Real(2)+Real(4))/2
Real(6)=(Real(0)+Real(6))/2
Real(7)=(Real(1)+Real(7))/2
Polygon(2)=A\x
Polygon(3)=A\y
Polygon(4)=M\x
Polygon(5)=M\y
Polygon(6)=B\x
Polygon(7)=B\y

ElseIf IsPointInsideRectancle2D(A\x,A\y,Polygon(2),Polygon(3),C\x,C\y,M\x,M\y,x,y)
Cross(A\x,A\y,2,RGB(160,160,160))
Cross(C\x,C\y,2,RGB(160,160,160))
Real(0)=(Real(0)+Real(2))/2
Real(1)=(Real(1)+Real(3))/2
Real(4)=(Real(0)+Real(2))/2
Real(5)=(Real(2)+Real(4))/2
Real(6)=(Real(0)+Real(6))/2
Real(7)=(Real(1)+Real(7))/2
Polygon(0)=A\x
Polygon(1)=A\y
Polygon(4)=C\x
Polygon(5)=C\y
Polygon(6)=M\x
Polygon(7)=M\y

ElseIf IsPointInsideRectancle2D(M\x,M\y,C\x,C\y,Polygon(4),Polygon(5),D\x,D\y,x,y)
Cross(C\x,C\y,2,RGB(160,160,160))
Cross(D\x,D\y,2,RGB(160,160,160))
Real(0)=(Real(0)+Real(2))/2
Real(1)=(Real(1)+Real(3))/2
Real(2)=(Real(2)+Real(4))/2
Real(3)=(Real(3)+Real(5))/2
Real(4)=(Real(4)+Real(6))/2
Real(5)=(Real(5)+Real(7))/2
Polygon(0)=M\x
Polygon(1)=M\y
Polygon(2)=C\x
Polygon(3)=C\y
Polygon(6)=D\x
Polygon(7)=D\y

ElseIf IsPointInsideRectancle2D(B\x,B\y,M\x,M\y,D\x,D\y,Polygon(6),Polygon(7),x,y)
Cross(B\x,B\y,2,RGB(160,160,160))
Cross(D\x,D\y,2,RGB(160,160,160))
Real(0)=(Real(0)+Real(6))/2
Real(1)=(Real(1)+Real(7))/2
Real(2)=(Real(0)+Real(2))/2
Real(3)=(Real(2)+Real(4))/2
Real(4)=(Real(6)+Real(4))/2
Real(5)=(Real(7)+Real(5))/2
Polygon(0)=B\x
Polygon(1)=B\y
Polygon(2)=M\x
Polygon(3)=M\y
Polygon(4)=D\x
Polygon(5)=D\y
Else
iteration=0
EndIf
Wend

For i=0 To 3
If x=Polygon(i<<1) And y=Polygon(i<<1+1)
x_=Real(i<<1)
y_=Real(i<<1+1)
EndIf
Next i

x_=(Real(0)+Real(4)) / 2
y_=(Real(1)+Real(5)) / 2

DrawText(x+10,y-25,Str(x_)+" | "+Str(y_),\$FF4040)

EndIf

StopDrawing()

EndProcedure

OpenWindow(0,0,0,#W,#H,"")
CreateImage(0,#W,#H,24)
UpdateImage()

Repeat
Select WaitWindowEvent()
Case #WM_MOUSEMOVE
UpdateImage()
Case #WM_CHAR
End
EndSelect
ForEver

Top

 Post subject: Re: Calculate real 3D coordinates from 2DPosted: Tue Mar 27, 2012 6:06 pm

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 1716
Eliminiated some bugs, but I've still no idea how to straighten the lines for a homogenous grid...
Another strange issue, the calculated x|y values seem to be completely wrong when moving the mouse cursor directly on a grid line.

Code:
; Define

#W=640
#H=480

Structure POINT_f
x.f
y.f
EndStructure

Global Dim Polygon(7)
Global Dim Real.f(7)

Global M.POINT_f
Global A.POINT_f
Global B.POINT_f
Global C.POINT_f
Global D.POINT_f

; EndDefine
Procedure InitValues()

Polygon(0)=40
Polygon(1)=40
Polygon(2)=340
Polygon(3)=30
Polygon(4)=550
Polygon(5)=300
Polygon(6)=100
Polygon(7)=440

Real(0)=-100
Real(1)=-100
Real(2)=100
Real(3)=-100
Real(4)=100
Real(5)=100
Real(6)=-100
Real(7)=100

EndProcedure
Procedure.i IsPointInsideTriangle2D(x0.f,y0.f,x1.f,y1.f,x2.f,y2.f,px.f,py.f)

Protected V1x.f=x1-x0
Protected V1y.f=y1-y0
Protected V2x.f=x2-x1
Protected V2y.f=y2-y1
Protected V3x.f=x0-x2
Protected V3y.f=y0-y2

If V1y*(px-x0)>=V1x*(py-y0)
If V2y*(px-x1)>=V2x*(py-y1) And V3y*(px-x2)>=V3x*(py-y2)
ProcedureReturn #True
EndIf
Else
If V2y*(px-x1)<V2x*(py-y1) And V3y*(px-x2)<V3x*(py-y2)
ProcedureReturn #True
EndIf
EndIf

ProcedureReturn #False

EndProcedure
Procedure.i IsPointInsideRectancle2D(x0.f,y0.f,x1.f,y1.f,x2.f,y2.f,x3.f,y3.f,x.f,y.f)

LineXY(x0,y0,x1,y1,RGB(60,80,60))
LineXY(x0,y0,x3,y3,RGB(60,80,60))
LineXY(x2,y2,x1,y1,RGB(60,80,60))
LineXY(x2,y2,x3,y3,RGB(60,80,60))

If IsPointInsideTriangle2D(x0,y0,x1,y1,x2,y2,x,y)
ProcedureReturn 1
EndIf
If IsPointInsideTriangle2D(x2,y2,x3,y3,x0,y0,x,y)
ProcedureReturn 2
EndIf

ProcedureReturn 0

EndProcedure
Procedure Cross(x,y,size,color)
LineXY(x-size,y-size,x+size,y+size,color)
LineXY(x+size,y-size,x-size,y+size,color)
EndProcedure
Procedure rectangleCenterPoint(*center.POINT_f, *TL.POINT, *TR.POINT, *BR.POINT, *BL.POINT)

Protected dy1.f = *TL\y - *BR\y
Protected dy2.f = *TR\y - *BL\y
Protected dx1.f = *TL\x - *BR\x
Protected dx2.f = *TR\x - *BL\x

If dx1 = 0 Or dx2 = 0
;one of the sides is vertical, use this simplified formula instead
*center\x =  (*TR\x + *BR\x) / 2
*center\y =  (*TR\y + *BR\y) / 2
Else
Protected m1.f = dy1 / dx1
Protected m2.f = dy2 / dx2
Protected b1.f = *TL\y - m1 * *TL\x
Protected b2.f = *TR\y - m2 * *TR\x
*center\x = (b2 - b1) / (m1 - m2)
*center\y = m1 * *center\x + b1
EndIf

EndProcedure
Procedure UpdateImage()

x=WindowMouseX(0)
y=WindowMouseY(0)

InitValues()

StartDrawing(ImageOutput(0))
Box(0,0,#W,#H,#Black)

DrawingMode(#PB_2DDrawing_Transparent)
For i=0 To 3
LineXY(Polygon(i<<1&7),Polygon(i<<1&7+1),Polygon((i<<1+2)&7),Polygon((i<<1+3)&7),#White)
DrawText(Polygon(i<<1&7),Polygon(i<<1&7+1),Str(Real(i<<1&7))+"|"+Str(Real(i<<1&7+1)),#Blue)
Next i

LineXY((Polygon(0)+Polygon(6))>>1,(Polygon(1)+Polygon(7))>>1,(Polygon(2)+Polygon(4))>>1,(Polygon(3)+Polygon(5))>>1,RGB(40,40,40))
LineXY((Polygon(0)+Polygon(2))>>1,(Polygon(1)+Polygon(3))>>1,(Polygon(6)+Polygon(4))>>1,(Polygon(7)+Polygon(5))>>1,RGB(40,40,40))

Select IsPointInsideRectancle2D(Polygon(0),Polygon(1),Polygon(2),Polygon(3),Polygon(4),Polygon(5),Polygon(6),Polygon(7),x,y)
Case 0
color=#Red
Case 1
color=#Green
Case 2
color=#Yellow
EndSelect

LineXY(x-29,y,x+29,y,color)
LineXY(x,y-29,x,y+29,color)

; ============================
; x_ and y_ have to be calculated here...
; ============================

If color<>#Red

Protected iteration=10

While iteration
iteration-1

RectangleCenterPoint(M,@Polygon(0),@Polygon(2),@Polygon(4),@Polygon(6))
Cross(M\x,M\y,iteration,RGB(160,160,160))

RectangleCenterPoint(A,@Polygon(0),@Polygon(2),@Polygon(0),@Polygon(2))
RectangleCenterPoint(B,@Polygon(0),@Polygon(6),@Polygon(0),@Polygon(6))
RectangleCenterPoint(C,@Polygon(2),@Polygon(4),@Polygon(2),@Polygon(4))
RectangleCenterPoint(D,@Polygon(4),@Polygon(6),@Polygon(4),@Polygon(6))

If IsPointInsideRectancle2D(Polygon(0),Polygon(1),A\x,A\y,M\x,M\y,B\x,B\y,x,y)
Cross(A\x,A\y,2,RGB(160,160,160))
Cross(B\x,B\y,2,RGB(160,160,160))
Real(2)=(Real(0)+Real(2))/2
Real(3)=(Real(1)+Real(3))/2
Real(4)=(Real(0)+Real(4))/2
Real(5)=(Real(1)+Real(5))/2
Real(6)=(Real(0)+Real(6))/2
Real(7)=(Real(1)+Real(7))/2
Polygon(2)=A\x
Polygon(3)=A\y
Polygon(4)=M\x
Polygon(5)=M\y
Polygon(6)=B\x
Polygon(7)=B\y

ElseIf IsPointInsideRectancle2D(A\x,A\y,Polygon(2),Polygon(3),C\x,C\y,M\x,M\y,x,y)
Cross(A\x,A\y,2,RGB(160,160,160))
Cross(C\x,C\y,2,RGB(160,160,160))
Real(0)=(Real(0)+Real(2))/2
Real(1)=(Real(1)+Real(3))/2
Real(4)=(Real(2)+Real(4))/2
Real(5)=(Real(3)+Real(5))/2
Real(6)=(Real(2)+Real(6))/2
Real(7)=(Real(3)+Real(7))/2
Polygon(0)=A\x
Polygon(1)=A\y
Polygon(4)=C\x
Polygon(5)=C\y
Polygon(6)=M\x
Polygon(7)=M\y

ElseIf IsPointInsideRectancle2D(M\x,M\y,C\x,C\y,Polygon(4),Polygon(5),D\x,D\y,x,y)
Cross(C\x,C\y,2,RGB(160,160,160))
Cross(D\x,D\y,2,RGB(160,160,160))
Real(0)=(Real(0)+Real(4))/2
Real(1)=(Real(1)+Real(5))/2
Real(2)=(Real(2)+Real(4))/2
Real(3)=(Real(3)+Real(5))/2
Real(6)=(Real(4)+Real(6))/2
Real(7)=(Real(5)+Real(7))/2
Polygon(0)=M\x
Polygon(1)=M\y
Polygon(2)=C\x
Polygon(3)=C\y
Polygon(6)=D\x
Polygon(7)=D\y

ElseIf IsPointInsideRectancle2D(B\x,B\y,M\x,M\y,D\x,D\y,Polygon(6),Polygon(7),x,y)
Cross(B\x,B\y,2,RGB(160,160,160))
Cross(D\x,D\y,2,RGB(160,160,160))
Real(0)=(Real(0)+Real(6))/2
Real(1)=(Real(1)+Real(7))/2
Real(2)=(Real(0)+Real(2))/2
Real(3)=(Real(2)+Real(4))/2
Real(4)=(Real(6)+Real(4))/2
Real(5)=(Real(7)+Real(5))/2
Polygon(0)=B\x
Polygon(1)=B\y
Polygon(2)=M\x
Polygon(3)=M\y
Polygon(4)=D\x
Polygon(5)=D\y
Else
iteration=0
EndIf

Wend

For i=0 To 3
If x=Polygon(i<<1) And y=Polygon(i<<1+1)
x_=Real(i<<1)
y_=Real(i<<1+1)
EndIf
Next i

x_=(Real(0)+Real(4)) / 2
y_=(Real(1)+Real(5)) / 2

DrawText(x+10,y-25,Str(x_)+" | "+Str(y_),\$FF4040)

EndIf

StopDrawing()

EndProcedure

OpenWindow(0,0,0,#W,#H,"")
CreateImage(0,#W,#H,24)
UpdateImage()

Repeat
Select WaitWindowEvent()
Case #WM_MOUSEMOVE
UpdateImage()
Case #WM_CHAR
End
EndSelect
ForEver

Top

 Post subject: Re: Calculate real 3D coordinates from 2DPosted: Mon Apr 02, 2012 10:07 am

Joined: Mon Jul 25, 2005 3:51 pm
Posts: 2401
Location: Utah, USA
I have found a solution using projection mapping. Which allows the mapping of an arbitrary quadrilateral to another quadrilateral. I translated some code that I found published on the internet from the University of California in 1989 entitled "Fundamentals of texture Mapping and Image Warping". It is easy to locate the document with an internet search if you want to see what it contains. This method works much better than subdividing the original polygon, which I see you did and I admit that I was tempted to do as well.

I would like to clean it up a little by whittling away anything that is unnecessary to your use. Of course I may just take the easy way out and let you do that.

I have a few more question before I share it. What kind of situations are you going to be using it for? Is it always going to be used for polygons and rectangle/squares of the same size? How are you determining the dimensions of the polygon and rectangle/map, are they from a map source?

_________________

Top

 Post subject: Re: Calculate real 3D coordinates from 2DPosted: Fri Apr 13, 2012 5:39 pm

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 1716
Demivec wrote:
I have found a solution using projection mapping. Which allows the mapping of an arbitrary quadrilateral to another quadrilateral. I translated some code that I found published on the internet from the University of California in 1989 entitled "Fundamentals of texture Mapping and Image Warping". It is easy to locate the document with an internet search if you want to see what it contains. This method works much better than subdividing the original polygon, which I see you did and I admit that I was tempted to do as well.

I would like to clean it up a little by whittling away anything that is unnecessary to your use. Of course I may just take the easy way out and let you do that.

I have a few more question before I share it. What kind of situations are you going to be using it for? Is it always going to be used for polygons and rectangle/squares of the same size? How are you determining the dimensions of the polygon and rectangle/map, are they from a map source?

Hi, I've been on holiday for a while, that's why this message has been a little bit delayed

I give you some information what I am doing (and what is my actual workaround for solving the problem above): I have written a program to do reports for sport activities which also shows GPS tracks in 3D. for doing this, I multiply matrices to convert 3D geo coordinates into 2D screen coordinates. Now I wanted to set waypoints (POIs) by doing a mouse click somewhere on the screen.

As I was not able to reverse the 3D–>2D conversion, I actually calculate the 2D coordinates for n×n geo coordinates, check which is the nearest to the mouse position, calculate n×n geo coordinates near this point and so on – not the best approach, but at least working.

Top

 Post subject: Re: Calculate real 3D coordinates from 2DPosted: Sat Apr 14, 2012 8:47 pm

Joined: Mon Jul 25, 2005 3:51 pm
Posts: 2401
Location: Utah, USA
Michael Vogel wrote:
As I was not able to reverse the 3D–>2D conversion, I actually calculate the 2D coordinates for n×n geo coordinates, check which is the nearest to the mouse position, calculate n×n geo coordinates near this point and so on – not the best approach, but at least working.

I cleaned up this code a little but I think you could probably tune it to your individual case better than I could. It converts between the coordinates of the screen point (sx, sy) and a texture point (u, v). In your case the texture is the geo cordinates.

projection_map.pbi
Code:
EnableExplicit
;Projection mapping routines translated from code presented in
;"Fundamentals of texture Mapping and Image Warping" by Paul S. Heckbert for his
;Master's Thesis at the University of California in 1989.
;
;Coded in PureBasic and adapted by Demivec.

Structure POINT_d
x.d
y.d
EndStructure

Structure poly_vert  ;a polygon vetex
u.d                ;texture space coordinates
v.d
sx.d               ;screen space coordinates
sy.d
EndStructure

vert.poly_vert[4]  ;vertices
EndStructure

;pmap return codes
Enumeration -1
#PMAP_AFFINE     ;mapping is affine
#PMAP_PROJECTIVE ;mapping is projective
EndEnumeration

;-matrix code
;Routines for manipulating 3 x 3 matrices
;These matrices are used to represent a 2-D projective mapping.

;Determinate for a 2x2 matrix.
Macro det2(a, b, c, d)
((a) * (d) - (b) * (c))
EndMacro

b(0, 0) = det2(a(1, 1), a(1, 2), a(2, 1), a(2, 2))
b(1, 0) = det2(a(1, 2), a(1, 0), a(2, 2), a(2, 0))
b(2, 0) = det2(a(1, 0), a(1, 1), a(2, 0), a(2, 1))
b(0, 1) = det2(a(2, 1), a(2, 2), a(0, 1), a(0, 2))
b(1, 1) = det2(a(2, 2), a(2, 0), a(0, 2), a(0, 0))
b(2, 1) = det2(a(2, 0), a(2, 1), a(0, 0), a(0, 1))
b(0, 2) = det2(a(0, 1), a(0, 2), a(1, 1), a(1, 2))
b(1, 2) = det2(a(0, 2), a(0, 0), a(1, 2), a(1, 0))
b(2, 2) = det2(a(0, 0), a(0, 1), a(1, 0), a(1, 1))

;If matrix is non-invertable the determinant will equal zero.
;The determinatnt may also equal zero due to floating point rounding errors.
ProcedureReturn a(0, 0) * b(0, 0) + a(0, 1) * b(0, 1) + a(0, 2) * b(0, 2)
EndProcedure

Procedure mx3d_mul(Array a.d(2), Array b.d(2), Array c.d(2))
;matrix multiply: c = a * b
c(0, 0) = a(0, 0) * b(0, 0) + a(0, 1) * b(1, 0) + a(0, 2) * b(2, 0)
c(0, 1) = a(0, 0) * b(0, 1) + a(0, 1) * b(1, 1) + a(0, 2) * b(2, 1)
c(0, 2) = a(0, 0) * b(0, 2) + a(0, 1) * b(1, 2) + a(0, 2) * b(2, 2)
c(1, 0) = a(1, 0) * b(0, 0) + a(1, 1) * b(1, 0) + a(1, 2) * b(2, 0)
c(1, 1) = a(1, 0) * b(0, 1) + a(1, 1) * b(1, 1) + a(1, 2) * b(2, 1)
c(1, 2) = a(1, 0) * b(0, 2) + a(1, 1) * b(1, 2) + a(1, 2) * b(2, 2)
c(2, 0) = a(2, 0) * b(0, 0) + a(2, 1) * b(1, 0) + a(2, 2) * b(2, 0)
c(2, 1) = a(2, 0) * b(0, 1) + a(2, 1) * b(1, 1) + a(2, 2) * b(2, 1)
c(2, 2) = a(2, 0) * b(0, 2) + a(2, 1) * b(1, 2) + a(2, 2) * b(2, 2)
EndProcedure

Procedure mx3d_transform(Array p.d(1), Array a_matrix.d(2), Array q.d(1)) ;the p & q matrices are 1x3
;transform point p by matrix a_Matrix: q = p * a_Matrix
q(0) = p(0) * a_matrix(0, 0) + p(1) * a_matrix(1, 0) + p(2) * a_matrix(2, 0)
q(1) = p(0) * a_matrix(0, 1) + p(1) * a_matrix(1, 1) + p(2) * a_matrix(2, 1)
q(2) = p(0) * a_matrix(0, 2) + p(1) * a_matrix(1, 2) + p(2) * a_matrix(2, 2)
EndProcedure

;-general projective mapping code
;General routines for 2-D projective mappings.
;are independent of the poly_quad structure, so we do not
;think in terms of texture and screen space.
#TOLERANCE = 1e-13
; Macro zero(x): ((x) < #TOLERANCE And (x) > -#TOLERANCE): EndMacro ;used in conditionals

;Find mapping between unit square and quadrilateral
;The correspondence is:
;

Protected.d px, py

If (px < #TOLERANCE And px > -#TOLERANCE) And (py < #TOLERANCE And py > -#TOLERANCE) ;affine
sq_matrix(0, 2) = 0
sq_matrix(1, 2) = 0
sq_matrix(2, 2) = 1
ProcedureReturn #PMAP_AFFINE
Else                     ;projective
Protected.d dx1, dx2, dy1, dy2, del

del = det2(dx1, dx2, dy1, dy2)

If del = 0
EndIf

sq_matrix(0, 2) = det2(px, dx2, py, dy2) / del
sq_matrix(1, 2) = det2(dx1, px, dy1, py) / del
sq_matrix(2, 2) = 1

ProcedureReturn #PMAP_PROJECTIVE
EndIf

EndProcedure

;Find mapping between quadrilateral and rectangle.
;The correspondence is:
;
;
;This method of computing the adjoint is numericaly cheaper than
;computing it symbolically.

;u0, v0, u1, v1: bounds of rectangle

Protected ret, du.d, dv.d
Protected Dim rq_matrix.d(2, 2) ;rect->quad transform

du = u1 - u0
dv = v1 - v0
If du = 0 Or dv = 0
EndIf

;first find mapping from unit uv square to xy quadrilateral

;concatenate transform from uv rectangle (u0, v0, u1, v1) to unit square
rq_matrix(0, 0) / du
rq_matrix(1, 0) / dv
rq_matrix(2, 0) - rq_matrix(0, 0) * u0 + rq_matrix(1, 0) * v0
rq_matrix(0, 1) / du
rq_matrix(1, 1) / dv
rq_matrix(2, 1) - rq_matrix(0, 1) * u0 + rq_matrix(1, 1) * v0
rq_matrix(0, 2) / du
rq_matrix(1, 2) / dv
rq_matrix(2, 2) - rq_matrix(0, 2) * u0 + rq_matrix(1, 2) * v0

;now rq_Matrix is transform from uv rectangle to xy quadrilateral
;qr_Matrix = inverse transform, which maps xy to uv
EndIf

ProcedureReturn ret
EndProcedure

;-projective mapping code
;Find the projective mapping st from screen to texture space
;given the screen and texture coordinates at the vertices of a polygon (specifically a quadrilateral).
;
;The alternative method, solving an 8x8 system of equations, takes longer.

Protected i, type1, type2
Protected Dim ms_matrix.d(2, 2)     ;mid_square->screen transform matrix
Protected Dim sm_matrix.d(2, 2)     ;screen->mid transform matrix
Protected Dim mt_matrix.d(2, 2)     ;mid->texture transform matrix

;prepare mid_square->screen transform matrix
For i = 0 To 3
Next

EndIf

;prepare mid->texture transform matrix
For i = 0 To 3
Next

EndIf

mx3d_mul(sm_matrix(), mt_matrix(), st_matrix())
ProcedureReturn type1 | type2 ;#PMAP_PROJECTIVE prevails over #PMAP_AFFINE
EndProcedure

;Find the projective mapping st from screen to texture space
;given the screen and texture coordinates at the vertices of a polygon (specifically a quadrilateral),
;which are passed in the fields (sx, sy) and (u, v) of p\vert[i], respectively.
With *p
If \vert[0]\v = \vert[1]\v And \vert[2]\v = \vert[3]\v And \vert[1]\u = \vert[2]\u And \vert[3]\u = \vert[0]\u
;edges 0-1 and 2-3 are horz, so 1-2 and 3-0 are vert

ElseIf \vert[0]\u = \vert[1]\u And \vert[2]\u = \vert[3]\u And \vert[1]\v = \vert[2]\v And \vert[3]\v = \vert[0]\v
;edges 0-1 and 2-3 are vert, so 1-2 and 3-0 are horz

Else
;texture is not an orthogonally-oriented rectangle
EndIf
EndWith
EndProcedure

DisableExplicit

Test code:
Code:
; Define
#mcolor = \$E0E0E0 ;\$8A8A8A
#ncolor = \$FFD0D0 ;\$4C804C
#pcolor = \$D0D0FF ;\$343434
#W=640
#H=480
XIncludeFile "projection_map.pbi"

Global Dim polygon(7)
Global Dim Real.d(7)
Global Dim screenToGeo.d(2, 2)
Global Dim geoToScreen.d(2, 2)
Global Dim screenCoord.d(2)
Global Dim screenCoord2.d(2)
Global Dim geoCoord.d(2)
Global Dim geoCoord2.d(2)

Procedure InitValues()

polygon(0)=40: polygon(1)=40
polygon(2)=340: polygon(3)=30
polygon(4)=550: polygon(5)=300
polygon(6)=100: polygon(7)=440

;test case 1 for another arbitrary polygon
; polygon(0)=66: polygon(1)=39
; polygon(2)=444: polygon(3)=33
; polygon(4)=300: polygon(5)=457
; polygon(6)=17: polygon(7)=440

Real(0)=-100: Real(1)=-100
Real(2)=100: Real(3)=-100
Real(4)=100: Real(5)=100
Real(6)=-100: Real(7)=100

;test case 1
;Other arbitrary rectangles used as geo coordinates, to test robustness of methods.
; Real(0)=-20: Real(1)=-30
; Real(2)=60: Real(3)=-30
; Real(4)=60: Real(5)=40
; Real(6)=-20: Real(7)=40

;test case 2
; Real(0)=-20: Real(1)=30
; Real(2)=60: Real(3)=30
; Real(4)=60: Real(5)=40
; Real(6)=-20: Real(7)=40

;set (sx, sy) for each vertex of screen quadrilateral along with the corresponding (u, v) geo points
;The following values is used for a reflection transformation to adjust for y axis being flipped
;between the screen and the geo cordinates. The value has only been tested based on a rectangular
;or square quadrilateral that is being used for the geo cordinates.
Protected dy.d = - Real(3) * 2 ;The least y value of the rectangle needs to be used for the reflection adjustment.
\vert[0]\u = Real(0): \vert[0]\v = Real(1) + dy: \vert[0]\sx = polygon(0): \vert[0]\sy = polygon(1)
\vert[1]\u = Real(2): \vert[1]\v = Real(3) + dy: \vert[1]\sx = polygon(2): \vert[1]\sy = polygon(3)
\vert[2]\u = Real(4): \vert[2]\v = Real(5) + dy: \vert[2]\sx = polygon(4): \vert[2]\sy = polygon(5)
\vert[3]\u = Real(6): \vert[3]\v = Real(7) + dy: \vert[3]\sx = polygon(6): \vert[3]\sy = polygon(7)
EndWith

EndProcedure

Procedure.i IsPointInsideTriangle2D(x0.d,y0.d,x1.d,y1.d,x2.d,y2.d,px.d,py.d)

Protected V1x.d=x1-x0
Protected V1y.d=y1-y0
Protected V2x.d=x2-x1
Protected V2y.d=y2-y1
Protected V3x.d=x0-x2
Protected V3y.d=y0-y2

If V1y*(px-x0)>=V1x*(py-y0)
If V2y*(px-x1)>=V2x*(py-y1) And V3y*(px-x2)>=V3x*(py-y2)
ProcedureReturn #True
EndIf
Else
If V2y*(px-x1)<V2x*(py-y1) And V3y*(px-x2)<V3x*(py-y2)
ProcedureReturn #True
EndIf
EndIf

ProcedureReturn #False

EndProcedure

Procedure.i IsPointInsideRectancle2D(x0.d,y0.d,x1.d,y1.d,x2.d,y2.d,x3.d,y3.d,x.d,y.d)

LineXY(x0,y0,x1,y1,#ncolor)
LineXY(x0,y0,x3,y3,#ncolor)
LineXY(x2,y2,x1,y1,#ncolor)
LineXY(x2,y2,x3,y3,#ncolor)

If IsPointInsideTriangle2D(x0,y0,x1,y1,x2,y2,x,y)
ProcedureReturn 1
EndIf
If IsPointInsideTriangle2D(x2,y2,x3,y3,x0,y0,x,y)
ProcedureReturn 2
EndIf

ProcedureReturn 0

EndProcedure

Procedure Cross(x,y,size,color)
LineXY(x-size,y-size,x+size,y+size,color)
LineXY(x+size,y-size,x-size,y+size,color)
EndProcedure

Procedure UpdateImage()

Protected x,y,color

x=WindowMouseX(0)
y=WindowMouseY(0)

;InitValues()

StartDrawing(ImageOutput(0))
Box(0,0,#W,#H,#Black)

DrawingMode(#PB_2DDrawing_Transparent)
For i=0 To 3
LineXY(polygon(i<<1&7),polygon(i<<1&7+1),polygon((i<<1+2)&7),polygon((i<<1+3)&7),#White)
DrawText(polygon(i<<1&7),polygon(i<<1&7+1),Str(Real(i<<1&7))+"|"+Str(Real(i<<1&7+1)),#Yellow)
Next i

;center point
geoCoord(0) = (Real(0) + Real(4)) / 2: geoCoord(1) = (Real(3) + Real(7)) / 2: geoCoord(2) = 1
mx3d_transform(geoCoord(), geoToScreen(), screenCoord())
Cross(screenCoord(0) / screenCoord(2), screenCoord(1) / screenCoord(2), 5, #pcolor)

Select IsPointInsideRectancle2D(polygon(0),polygon(1),polygon(2),polygon(3),polygon(4),polygon(5),polygon(6),polygon(7),x,y)
Case 0
color=#Red
Case 1
color=#Green
Case 2
color=#Yellow
EndSelect

;cross hairs
LineXY(x-29,y,x+29,y,color)
LineXY(x,y-29,x,y+29,color)

If color<>#Red

; x_ and y_ are calculated here...
screenCoord(0) = x: screenCoord(1) = y: screenCoord(2) = 1
mx3d_transform(screenCoord(), screenToGeo(), geoCoord())
Protected.d x_, y_
x_ = geoCoord(0) / geoCoord(2)
y_ = geoCoord(1) / geoCoord(2)

;horizontal line
geoCoord(0) = Real(0): geoCoord(1) = y_: geoCoord(2) = 1
mx3d_transform(geoCoord(), geoToScreen(), screenCoord())
geoCoord2(0) = Real(4): geoCoord2(1) = y_: geoCoord2(2) = 1
mx3d_transform(geoCoord2(), geoToScreen(), screenCoord2())
LineXY(screenCoord(0) / screenCoord(2), screenCoord(1) / screenCoord(2), screenCoord2(0) / screenCoord2(2), screenCoord2(1) / screenCoord2(2), #White)

;vertical line
geoCoord(0) = x_: geoCoord(1) = Real(3): geoCoord(2) = 1
mx3d_transform(geoCoord(), geoToScreen(), screenCoord())
geoCoord2(0) = x_: geoCoord2(1) = Real(7): geoCoord2(2) = 1
mx3d_transform(geoCoord2(), geoToScreen(), screenCoord2())
LineXY(screenCoord(0) / screenCoord(2), screenCoord(1) / screenCoord(2), screenCoord2(0) / screenCoord2(2), screenCoord2(1) / screenCoord2(2), #White)

DrawText(x+10,y-25,Str(x_)+" | "+Str(y_), #Yellow)

EndIf

StopDrawing()

EndProcedure

OpenWindow(0,0,0,#W,#H,"")
CreateImage(0,#W,#H,24)
InitValues()

;compute screen to geo transform
If Not mx3d_adjoint(screenToGeo(), geoToScreen()): End: EndIf

UpdateImage()

Repeat
Select WaitWindowEvent()
Case #WM_MOUSEMOVE
UpdateImage()
Case #WM_CHAR
End
EndSelect
ForEver

I believe this does what you wanted.

I had one small problem that required some additional work to resolve. I setup two quadrilaterals with the coordinates you gave (Real(), and Polygon()). I then use the routines to create the transform matrices to convert between the two sets of coordinates. The problem that occurs required me to reflect the Real() coordinates to account for the flipping of the Y axis betwen the quadrilaterals defined by the Polygon() and the Real() coordinates. Either set of coordinates could probably have been used and so I chose the Real() ones because they were rectangular and thereby easier to do.

I'm going to see if I can add the reflective transformation, in a separate procedure call, that combines it as a matrix with the transformation matrix that has already been produced. This would allow referencing the original coordinates without them becoming distorted by the way the reflection transformation is in the current code.

This change distorts the copy of the coordinates because the reflected Y values are not the same as the originals. This means if you want to reference them, such as for displaying them for instance, you need to look to another copy of them (i.e. the ones stored in Real()). I do this when positioning things on the screen polygon based on the geo coordinates when displaying the center point and lines traversing the polygon based on the mouse position.

I did enough testing to recommend this as a good solution. I am going to explore other useful aspects of the projection mapping routines and possibly post them in the Tips & Tricks forum because of their usefullness.

@Edit: updated code, and explanatory test

_________________

Top

 Post subject: Re: Calculate real 3D coordinates from 2DPosted: Wed Apr 18, 2012 6:13 pm

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 1716
Demivec,
thanks for your posting – it will take a while until I can play with it, actually I have have to work around 30 hours a day*, but I will check your code as soon as possible.

___
*) actually I don't care about number representations, even in an octal world

Top

 Post subject: Re: Calculate real 3D coordinates from 2DPosted: Wed Apr 18, 2012 9:24 pm

Joined: Mon Jul 25, 2005 3:51 pm
Posts: 2401
Location: Utah, USA
Michael Vogel wrote:
thanks for your posting – it will take a while until I can play with it, actually I have have to work around 30 hours a day*, but I will check your code as soon as possible.

You sound like you are working way too much, slow down to only 29 or maybe 28 hours a day.

Here's a final update. I had thought that what was needed was a reflective transform, which I had added manually before. It turns out it wasn't needed and what I actually was doing was a translation transform. I have added a procedure to the example code that performs this and adds it to the transformations already present in the projection mapping (it's added before them). This modification will leave the original coordinates of both the polygon and its corresponding geo mapped coordinates at their original values so that they can be referred to as needed. This means that you wouldn't need a separate variable for either the Polygon() or the Real() coordinates if you didn't want to, all coordinate changes that are needed are in the transformation matrices.

The include file 'projection map.pbi' remains unchanged.

Here is the changed example code:
Code:
; Define
#mcolor = \$E0E0E0 ;\$8A8A8A
#ncolor = \$FFD0D0 ;\$4C804C
#pcolor = \$D0D0FF ;\$343434
#W=640
#H=480
XIncludeFile "projection_map.pbi"

Global Dim polygon(7)
Global Dim Real.d(7)
Global Dim screenToGeo.d(2, 2)
Global Dim geoToScreen.d(2, 2)
Global Dim screenCoord.d(2)
Global Dim screenCoord2.d(2)
Global Dim geoCoord.d(2)
Global Dim geoCoord2.d(2)

Procedure InitValues()

polygon(0)=40: polygon(1)=40
polygon(2)=340: polygon(3)=30
polygon(4)=550: polygon(5)=300
polygon(6)=100: polygon(7)=440

;test case 1 for another arbitrary polygon
; polygon(0)=66: polygon(1)=39
; polygon(2)=444: polygon(3)=33
; polygon(4)=300: polygon(5)=457
; polygon(6)=17: polygon(7)=440

Real(0)=-100: Real(1)=-100
Real(2)=100: Real(3)=-100
Real(4)=100: Real(5)=100
Real(6)=-100: Real(7)=100

;test case 1
;Other arbitrary rectangles used as geo coordinates, to test robustness of methods.
; Real(0)=-20: Real(1)=-30
; Real(2)=60: Real(3)=-30
; Real(4)=60: Real(5)=40
; Real(6)=-20: Real(7)=40

;test case 2, minimum Y > 0
; Real(0)=-20: Real(1)=30
; Real(2)=60: Real(3)=30
; Real(4)=60: Real(5)=40
; Real(6)=-20: Real(7)=40

;test case 3, maximum Y < 0 and Y axis reversed compared to polygon
; Real(0)=-20: Real(1)=-30
; Real(2)=60: Real(3)=-30
; Real(4)=60: Real(5)=-40
; Real(6)=-20: Real(7)=-40

;set (sx, sy) for each vertex of screen quadrilateral along with the corresponding (u, v) geo points
\vert[0]\u = Real(0): \vert[0]\v = Real(1): \vert[0]\sx = polygon(0): \vert[0]\sy = polygon(1)
\vert[1]\u = Real(2): \vert[1]\v = Real(3): \vert[1]\sx = polygon(2): \vert[1]\sy = polygon(3)
\vert[2]\u = Real(4): \vert[2]\v = Real(5): \vert[2]\sx = polygon(4): \vert[2]\sy = polygon(5)
\vert[3]\u = Real(6): \vert[3]\v = Real(7): \vert[3]\sx = polygon(6): \vert[3]\sy = polygon(7)
EndWith

EndProcedure

Procedure.i IsPointInsideTriangle2D(x0.d,y0.d,x1.d,y1.d,x2.d,y2.d,px.d,py.d)

Protected V1x.d=x1-x0
Protected V1y.d=y1-y0
Protected V2x.d=x2-x1
Protected V2y.d=y2-y1
Protected V3x.d=x0-x2
Protected V3y.d=y0-y2

If V1y*(px-x0)>=V1x*(py-y0)
If V2y*(px-x1)>=V2x*(py-y1) And V3y*(px-x2)>=V3x*(py-y2)
ProcedureReturn #True
EndIf
Else
If V2y*(px-x1)<V2x*(py-y1) And V3y*(px-x2)<V3x*(py-y2)
ProcedureReturn #True
EndIf
EndIf

ProcedureReturn #False

EndProcedure

Procedure.i IsPointInsideRectancle2D(x0.d,y0.d,x1.d,y1.d,x2.d,y2.d,x3.d,y3.d,x.d,y.d)

LineXY(x0,y0,x1,y1,#ncolor)
LineXY(x0,y0,x3,y3,#ncolor)
LineXY(x2,y2,x1,y1,#ncolor)
LineXY(x2,y2,x3,y3,#ncolor)

If IsPointInsideTriangle2D(x0,y0,x1,y1,x2,y2,x,y)
ProcedureReturn 1
EndIf
If IsPointInsideTriangle2D(x2,y2,x3,y3,x0,y0,x,y)
ProcedureReturn 2
EndIf

ProcedureReturn 0

EndProcedure

Procedure Cross(x,y,size,color)
LineXY(x-size,y-size,x+size,y+size,color)
LineXY(x+size,y-size,x-size,y+size,color)
EndProcedure

Procedure UpdateImage()

Protected x,y,color

x=WindowMouseX(0)
y=WindowMouseY(0)

;InitValues()
StartDrawing(ImageOutput(0))
Box(0,0,#W,#H,#Black)

DrawingMode(#PB_2DDrawing_Transparent)
For i=0 To 3
LineXY(polygon(i<<1&7),polygon(i<<1&7+1),polygon((i<<1+2)&7),polygon((i<<1+3)&7),#White)
DrawText(polygon(i<<1&7),polygon(i<<1&7+1),Str(Real(i<<1&7))+"|"+Str(Real(i<<1&7+1)),#Yellow)
Next i

;center point

;geoCoord(0) = (Real(0) + Real(4)) / 2: geoCoord(1) = (Real(3) + Real(7)) / 2: geoCoord(2) = 1
geoCoord(0) = (\vert[0]\u + \vert[2]\u) / 2: geoCoord(1) = (\vert[1]\v + \vert[3]\v) / 2: geoCoord(2) = 1
mx3d_transform(geoCoord(), geoToScreen(), screenCoord())
Cross(screenCoord(0) / screenCoord(2), screenCoord(1) / screenCoord(2), 5, #pcolor)

Select IsPointInsideRectancle2D(polygon(0),polygon(1),polygon(2),polygon(3),polygon(4),polygon(5),polygon(6),polygon(7),x,y)
Case 0
color=#Red
Case 1
color=#Green
Case 2
color=#Yellow
EndSelect

;cross hairs
LineXY(x-29,y,x+29,y,color)
LineXY(x,y-29,x,y+29,color)

If color<>#Red

; x_ and y_ are calculated here...
screenCoord(0) = x: screenCoord(1) = y: screenCoord(2) = 1
mx3d_transform(screenCoord(), screenToGeo(), geoCoord())
Protected.d x_, y_
x_ = geoCoord(0) / geoCoord(2)
y_ = geoCoord(1) / geoCoord(2)

;horizontal line
geoCoord(0) = \vert[0]\u: geoCoord(1) = y_: geoCoord(2) = 1
mx3d_transform(geoCoord(), geoToScreen(), screenCoord())
geoCoord2(0) = \vert[2]\u: geoCoord2(1) = y_: geoCoord2(2) = 1
mx3d_transform(geoCoord2(), geoToScreen(), screenCoord2())
LineXY(screenCoord(0) / screenCoord(2), screenCoord(1) / screenCoord(2), screenCoord2(0) / screenCoord2(2), screenCoord2(1) / screenCoord2(2), #White)

;vertical line
geoCoord(0) = x_: geoCoord(1) = \vert[1]\v: geoCoord(2) = 1
mx3d_transform(geoCoord(), geoToScreen(), screenCoord())
geoCoord2(0) = x_: geoCoord2(1) = \vert[3]\v: geoCoord2(2) = 1
mx3d_transform(geoCoord2(), geoToScreen(), screenCoord2())
LineXY(screenCoord(0) / screenCoord(2), screenCoord(1) / screenCoord(2), screenCoord2(0) / screenCoord2(2), screenCoord2(1) / screenCoord2(2), #White)

DrawText(x+10,y-25,Str(x_)+" | "+Str(y_), #Yellow)

EndIf

StopDrawing()
EndWith

EndProcedure

Procedure translationTransform(*p.poly_quad, Array t.d(2)) ;t() is a matrix to update by adding a translation transform to it
Protected dy.d = *p\vert[1]\v * 2
Protected Dim t2.d(2, 2)
Protected Dim r.d(2, 2)
CopyArray(t(), t2()) ;this allows us to output the original matrix with our changes
r(0, 0) = 1: r(1, 0) =  0: r(2, 0) = 0
r(0, 1) = 0: r(1, 1) = 1: r(2, 1) = dy
r(0, 2) = 0: r(1, 2) =  0: r(2, 2) = 1
mx3d_mul(t2(), r(), t())
EndProcedure

OpenWindow(0,0,0,#W,#H,"")
CreateImage(0,#W,#H,24)
InitValues()

;compute screen to geo transform
If Not mx3d_adjoint(screenToGeo(), geoToScreen()): End: EndIf ;Abort, transforms can't be inverted

UpdateImage()

Repeat
Select WaitWindowEvent()
Case #WM_MOUSEMOVE
UpdateImage()
Case #WM_CHAR
End
EndSelect
ForEver

One interesting to note is that as a result of adding the translation transform the code will actually peform a reflection along the Y axis if needed. I provided a test case to prove it. I think that should provide most, if not all of what you need. Let me know how things turn out.

_________________

Top

 Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending
 Page 1 of 1 [ 9 posts ]

 All times are UTC + 1 hour

#### Who is online

Users browsing this forum: No registered users and 4 guests

 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forum

Search for:
 Jump to:  Select a forum ------------------ PureBasic    Coding Questions    Game Programming    3D Programming    Assembly Programming    The PureBasic Editor    The PureBasic Form Designer    General Discussion    Feature Requests and Wishlists    Tricks 'n' Tips Bug Reports    Bugs - Windows    Bugs - Linux    Bugs - Mac OSX    Bugs - Documentation OS Specific    AmigaOS    Linux    Windows    Mac OSX Miscellaneous    Announcement    Off Topic Showcase    Applications - Feedback and Discussion    PureFORM & JaPBe    TailBite