﻿B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=StaticCode
Version=13
@EndOfDesignText@
'Code module
'Subs in this code module will be accessible from all modules.
Sub Process_Globals
	'These global variables will be declared once when the application starts.
	'These variables can be accessed from all modules.
	
	Public lTime As Long
	Private iMapPoints As Int ' Pontok száma
	Private arrPoints() As TMapLatLng
	Private arrHull() As Int
	Private arrbHull_Busy() As Boolean
	Private iHull_C As Int
	Private pi As Float = 3.14159265358
	'Private arrLimits(6) As Double 'not needed anymore
	Private bWorking As Boolean
	
	Private Const cMinLat As Double = -85.0511
	Private Const cMaxLat As Double = 85.0511
	Private Const cMinLng As Double = -180.0
	Private Const cMaxLng As Double = 180.0

	Type TMapLatLng(fLat As Double, fLng As Double)

End Sub

'return a valid lat
Public Sub validLat(aLat As Double) As Double
	Return Max(cMinLat,Min(aLat,cMaxLat))
End Sub

'return a valid lng
Public Sub validLng(aLng As Double) As Double
	Return Max(cMinLng,Min(aLng,cMaxLng))
End Sub

Public Sub initLatLng(aLat As Double, aLng As Double) As TMapLatLng
	Dim ll As TMapLatLng
	ll.Initialize
	ll.fLat=validLat(aLat)
	ll.fLng=validLng(aLng)
	Return ll
End Sub

Sub Reset(lstMapLatLonPoints As List, fAcc As Double)

	iMapPoints = lstMapLatLonPoints.Size
	
	'if fAcc has a high value then there could be more border points than map points!
	'--------------------------------------------------------------------------------
	Dim arrHull(iMapPoints * fAcc) As Int
	Dim arrbHull_Busy(iMapPoints * fAcc) As Boolean
	
	Dim arrPoints(iMapPoints) As TMapLatLng
	Dim tLL As TMapLatLng
	'Dim arrLimits(6) As Double 'not needed anymore
	
	iHull_C = 0

	bWorking = False
	
	'this used to be done by Sub AddPoints
	'-------------------------------------
	For i = 0 To lstMapLatLonPoints.Size - 1
		tLL = lstMapLatLonPoints.Get(i)
		arrPoints(i) = tLL
	Next
	
End Sub

Sub GetBorderPoints(lstMapLatLonPoints As List, fAcc As Double) As ResumableSub
	
	Dim i As Int
	Dim fMinY As Double = 99999999
	Dim fRang As Double  = 2 * pi
	Dim iMinAng_Ind As Int
	Dim iMinAng_NoLimit_Ind As Int
	Dim fMinAng_Ang As Double
	Dim fMinAng_NoLimit_Ang As Double
	Dim fMinAng_NoLimit_Dis  As Double
	Dim fDis As Double
	Dim fDis0 As Double
	Dim fDis1 As Double
	Dim fang As Double
	Dim iAktP As Int
	
	Dim bChange As Boolean
	Dim bNoOK As Boolean

	Dim iH1 As Int
	Dim iH2 As Int
	Dim iMinDis_Ind As Int
	Dim fMinDis As Double
	Dim fDis0 As Double
	Dim fDis1 As Double
	Dim fDis3 As Double
	Dim fDis4 As Double
	
	Dim tLL As TMapLatLng
	Dim lstBorderPoints As List
	
	lTime = DateTime.Now
	
	Reset(lstMapLatLonPoints, fAcc)
	
'	'this used to be done by Sub AddPoints
'	'-------------------------------------
'	For i = 0 To lstMapLatLonPoints.Size - 1
'		tLL = lstMapLatLonPoints.Get(i)
'		arrPoints(i) = tLL
'	Next

	bWorking = True
	
	For i = 0 To iMapPoints - 1
		If arrPoints(i).fLat < fMinY Then
			iAktP = i
			fMinY = arrPoints(i).fLat
		End If
	Next

	' A legalsó pontot kiemelni (piros szín)
	Add_Hull(iAktP, 0)

	'-------------------------------------------------------------- STANDARD FRAME
	Do While True
		'keresse a legkozelebbit,aminek a legkisebb a szoge,
		iMinAng_Ind = -1
		fMinAng_Ang = 999999

		iMinAng_NoLimit_Ind = -1
		fMinAng_NoLimit_Ang = 999999
		fMinAng_NoLimit_Dis = 999999

		For i = 0 To iMapPoints - 1
			If i = iAktP Then Continue
			fDis0 = arrPoints(i).fLng - arrPoints(iAktP).fLng
			fDis1 = arrPoints(i).fLat - arrPoints(iAktP).fLat
			fDis = Sqrt(fDis0 * fDis0 + fDis1 * fDis1)
			fang = DifAng(fRang, ATan2(fDis0, fDis1))

			If fang < fMinAng_NoLimit_Ang And fDis < fMinAng_NoLimit_Dis Then
				fMinAng_NoLimit_Ang = fang
				fMinAng_NoLimit_Dis = fDis
				iMinAng_NoLimit_Ind = i
			End If

			If fang < fMinAng_Ang Then
				fMinAng_Ang = fang
				iMinAng_Ind = i
			End If
		Next

		If iMinAng_Ind = -1 Then
			iMinAng_Ind = iMinAng_NoLimit_Ind
			fMinAng_Ang = fMinAng_NoLimit_Ang
		End If
		'    Line (points(iAktP, 0), points(iAktP, 1))-(points(iMinAng_Ind, 0), points(iMinAng_Ind, 1))

		If iAktP = arrHull(0) And iHull_C > 2 Then Exit
		Add_Hull(iAktP, iHull_C)

		fRang = ATan2(arrPoints(iAktP).fLng - arrPoints(iMinAng_Ind).fLng, arrPoints(iAktP).fLat - arrPoints(iMinAng_Ind).fLat)
		iAktP = iMinAng_Ind

	Loop

	'-------------------------------------  FRAME RESOLUTION

	Do While True  'For qqw = 0 To 100
		
		bChange = False
		iH1 = 0
		
		Do While True
			iH2 = (iH1 + 1) Mod (iHull_C - 0)

			fMinDis = 999999
			iMinDis_Ind = -1
        
			fDis3 = Sqrt(Power(arrPoints(arrHull(iH2)).fLng - arrPoints(arrHull(iH1)).fLng,2)  + Power((arrPoints(arrHull(iH2)).fLat - arrPoints(arrHull(iH1)).fLat),2))
			
			For ind = 0 To iMapPoints - 1
				If arrbHull_Busy(ind)  Then Continue
				fDis0 = Sqrt(Power(arrPoints(ind).fLng - arrPoints(arrHull(iH1)).fLng, 2)  + Power((arrPoints(ind).fLat - arrPoints(arrHull(iH1)).fLat), 2))
				fDis1 = Sqrt(Power(arrPoints(ind).fLng - arrPoints(arrHull(iH2)).fLng, 2)  + Power((arrPoints(ind).fLat - arrPoints(arrHull(iH2)).fLat), 2))

				fDis4 = fDis0 + fDis1
				If fDis3 * fAcc > fDis4 And (fDis4 < fMinDis) Then
					fMinDis = fDis4
					iMinDis_Ind = ind
				End If
			Next

			If iMinDis_Ind <> -1 Then
				bNoOK = Add_Hull(iMinDis_Ind, iH2)
				If bNoOK  Then
					iH1 = iH1 + 1
					bChange = True
				End If
			End If

			iH1 = iH1 + 1
			If iH1 > iHull_C - 1 Then Exit
		Loop
		If bChange = False Then Exit
	Loop

	'this is not needed anymore
	'--------------------------
	'Calc_Limits
	
	bWorking = False
	
	lstBorderPoints.Initialize
	
	For i = 0 To iHull_C - 1
		tLL = initLatLng(arrPoints(arrHull(i)).fLat, arrPoints(arrHull(i)).fLng)
		lstBorderPoints.Add(tLL)
	Next
	
	tLL = initLatLng(arrPoints(arrHull(0)).fLat, arrPoints(arrHull(0)).fLng)
	lstBorderPoints.Add(tLL)
	
	lTime = DateTime.Now - lTime
	
	Return lstBorderPoints
	
End Sub

Sub Add_Hull (iInd As Int, iHova As Int ) As Boolean
	
'	Log("Add_Hull, iHull_C: " & iHull_C)
'	Log("Add_Hull, iInd: " & iInd)
'	Log("Add_Hull, iHova: " & iHova)
	
	'vizsgalat
	Dim t As Int
	Dim bOK As Boolean= True
	Dim bFelt As Boolean
	Dim iT0 As Int
	Dim iT1 As Int
	Dim iT3 As Int

	'mentes elkeszitese
	Dim arrmHull(iHull_C + 10) As Int
	
	For t = 0 To iHull_C - 1
		arrmHull(t) = arrHull(t)
	Next

	'beiktat
	iHull_C = iHull_C + 1

	For t = iHull_C - 2 To iHova Step -1
		arrHull(t + 1) = arrHull(t)
	Next

	arrHull(iHova) = iInd
	
	'    GoTo 66
	For iT0 = 0 To iHull_C - 1
		iT1 = (iT0 + 1) Mod iHull_C
		For t2 = 0 To iHull_C - 1
			iT3 = (t2 + 1) Mod iHull_C
			bFelt = (arrHull(iT0) = arrHull(t2) Or arrHull(iT0) = arrHull(iT3))
			bFelt = (arrHull(iT1) = arrHull(t2) Or arrHull(iT1) = arrHull(iT3)) Or bFelt
			If bFelt Then Continue
			If IsIntersection(arrPoints(arrHull(iT0)).fLng, arrPoints(arrHull(iT0)).fLat, arrPoints(arrHull(iT1)).fLng, arrPoints(arrHull(iT1)).fLat, arrPoints(arrHull(t2)).fLng, arrPoints(arrHull(t2)).fLat, arrPoints(arrHull(iT3)).fLng, arrPoints(arrHull(iT3)).fLat) Then bOK = False
		Next
	Next

	'    ok = 1

	If bOK = False Then
		For t = 0 To iHull_C - 1
			arrHull(t) = arrmHull(t)
		Next
		iHull_C = iHull_C - 1
	Else
		arrbHull_Busy(iInd) = True
	End If

	Return bOK

End Sub

Sub DifAng (fAngle1 As Double, fAngle2 As Double) As Double
	
	Dim fDiff As Double
	Dim fC As Double =  2 * pi

	Do Until fAngle1 < fC
		fAngle1 = fAngle1 - fC
	Loop

	Do Until fAngle1 >= 0
		fAngle1 = fAngle1 + fC
	Loop

	Do Until fAngle2 < fC
		fAngle2 = fAngle2 - fC
	Loop

	Do Until fAngle2 >= 0
		fAngle2 = fAngle2 + fC
	Loop

	fDiff = fAngle1 - fAngle2

	If fDiff < -pi Then fDiff = fDiff + 2 * pi
	If fDiff > pi Then fDiff = fDiff - 2 * pi

	Return fDiff
	
End Sub

Sub IsIntersection (fX1 As Double, fY1 As Double, fX2 As Double, fY2 As Double, fX3 As Double, fY3 As Double, fX4 As Double, fY4 As Double) As Boolean
	
	Dim fDenominator As Double
	Dim fUA As Double
	Dim fUB As Double
	
	fDenominator = (fY4 - fY3) * (fX2 - fX1) - (fX4 - fX3) * (fY2 - fY1)
	
	If fDenominator = 0 Then
		Return False 'IsIntersection = 0
	Else
		fUA = ((fX4 - fX3) * (fY1 - fY3) - (fY4 - fY3) * (fX1 - fX3)) / fDenominator
		fUB = ((fX2 - fX1) * (fY1 - fY3) - (fY2 - fY1) * (fX1 - fX3)) / fDenominator
		Return fUA >= 0 And fUA <= 1 And fUB >= 0 And fUB <= 1
	End If
	
End Sub