Post ini ada kaitannya dgn post saya yg ini. Jadi tool utk predict dan scoring neighbor yg sebelumnya dibikin pke VBA, skrg dibikin pke mapbasic. Tentu keuntungannya yaitu hasil dr prediksi dan scoring nya bisa lngsung keliatan di mapinfo.
Konsepnya sederhana aja sih, yg dikatakan best neighbor list menurut tool ini yaitu yg attempt ncell nya besar, jarak paling deket, posisi site target yg ada di beam radius si source, ama azimuth si target nya yg ngarah ke source.
Modal utk ngbikin prediction dan scoring ya cuma 3 table yaitu data cell, Nbr table, dan NCell table. Kita coba bahas dulu utk 3G to 3G prediction and scoring aja dulu (toh 3G ke 2G dan 2G ke 2G sama aja koq konsepnya, cuma table2 nya aja diganti).
Detail mapbasic codenya beginih.. (moga bermanfaat dan klo ada yg punya ide lain utk metode prediksinya boleh donk di sharing ilmunya hehe)
Detail mapbasic codenya beginih.. (moga bermanfaat dan klo ada yg punya ide lain utk metode prediksinya boleh donk di sharing ilmunya hehe)
Predict Neighbors :
if isUseSHOforPredict=1 then
select * from SHO_NCell where Source=sourceId into qCreateSHO noselect
Commit Table qCreateSHO As myAppDir + "Table\tmpSHO_NCell.TAB" TYPE NATIVE Charset "WindowsLatin1"
Open Table myAppDir + "Table\tmpSHO_NCell.TAB" Interactive
close table qCreateSHO
select Max(SHO_Att) "MaxSHO" from tmpSHO_NCell where Source=sourceId into qSHO noselect
fMaxSHO=qSHO.MaxSHO
close table qSHO
end if
select * from Data_3G_Cell where Carrier=sCarrierTarget3G and Distance( startX, startY, Longitude, Latitude, "km" ) <= fMaxDistance into qRel
do while not EOT(qRel)
targetId=qRel.RNC_CellID
tx=centroidx(qRel.Obj)
ty=centroidy(qRel.Obj)
endX=qRel.Longitude
endY=qRel.Latitude
aztarget=qRel.Azimuth
if sourceId<>targetId then
'read SHO att value
if isUseSHOforPredict=1 then
select * from tmpSHO_NCell where Source=sourceId and Target=targetId into qSHO noselect
currentSHO=qSHO.SHO_Att
if fMaxSHO > 0 then
fRateSHO=(currentSHO/fMaxSHO)*100
else
fRateSHO=0
end if
close table qSHO
else
currentSHO=0
fRateSHO=0
end if
'calculate rate distance
fRateDistance=((fMaxDistance - Distance(startX,startY,endX,endY,"km")) / fMaxDistance) * 100
'calculate rate azimuth
call analyzeNeighbour(startX,startY,endX,endY,azsource,aztarget,fRingWidth)
'calculate average rate
call calculate_AverageRate
'insert to tblPredict
insert into tblPredict (Source,Target,SHO_Att,Distance_Km,Rate_SHO,Rate_Distance,Rate_Ring,Rate_TargetToBothDir,Rate_TargetToSource,Rate_Average)
values (sourceId,targetId,currentSHO,Distance(startX,startY,endX,endY,"km"),fRateSHO,fRateDistance,fRateRing,fRateBothDir,fRateAntDir,fRateAverage)
end if
fetch next from qRel
loop
select * from SHO_NCell where Source=sourceId into qCreateSHO noselect
Commit Table qCreateSHO As myAppDir + "Table\tmpSHO_NCell.TAB" TYPE NATIVE Charset "WindowsLatin1"
Open Table myAppDir + "Table\tmpSHO_NCell.TAB" Interactive
close table qCreateSHO
select Max(SHO_Att) "MaxSHO" from tmpSHO_NCell where Source=sourceId into qSHO noselect
fMaxSHO=qSHO.MaxSHO
close table qSHO
end if
select * from Data_3G_Cell where Carrier=sCarrierTarget3G and Distance( startX, startY, Longitude, Latitude, "km" ) <= fMaxDistance into qRel
do while not EOT(qRel)
targetId=qRel.RNC_CellID
tx=centroidx(qRel.Obj)
ty=centroidy(qRel.Obj)
endX=qRel.Longitude
endY=qRel.Latitude
aztarget=qRel.Azimuth
if sourceId<>targetId then
'read SHO att value
if isUseSHOforPredict=1 then
select * from tmpSHO_NCell where Source=sourceId and Target=targetId into qSHO noselect
currentSHO=qSHO.SHO_Att
if fMaxSHO > 0 then
fRateSHO=(currentSHO/fMaxSHO)*100
else
fRateSHO=0
end if
close table qSHO
else
currentSHO=0
fRateSHO=0
end if
'calculate rate distance
fRateDistance=((fMaxDistance - Distance(startX,startY,endX,endY,"km")) / fMaxDistance) * 100
'calculate rate azimuth
call analyzeNeighbour(startX,startY,endX,endY,azsource,aztarget,fRingWidth)
'calculate average rate
call calculate_AverageRate
'insert to tblPredict
insert into tblPredict (Source,Target,SHO_Att,Distance_Km,Rate_SHO,Rate_Distance,Rate_Ring,Rate_TargetToBothDir,Rate_TargetToSource,Rate_Average)
values (sourceId,targetId,currentSHO,Distance(startX,startY,endX,endY,"km"),fRateSHO,fRateDistance,fRateRing,fRateBothDir,fRateAntDir,fRateAverage)
end if
fetch next from qRel
loop
Analyze Neighbors :
Sub analyzeNeighbour(ByVal StartLong as float,ByVal StartLat as float,ByVal EndLong as float,ByVal EndLat as float,ByVal fDirSource as float,ByVal fDirTarget as float,ByVal fRingWidth as float)
if fDirSource >= 0 and fDirSource < 90 then
mapDirSource = 90 - fDirSource
elseif fDirSource >= 90 and fDirSource < 180 then
mapDirSource = 360 - (fDirSource - 90)
elseif fDirSource >= 180 and fDirSource < 270 then
mapDirSource = 180 + (270 - fDirSource)
elseif fDirSource >= 270 and fDirSource <= 360 then
mapDirSource = 90 + (360 - fDirSource)
end if
if fDirTarget >= 0 and fDirTarget < 90 then
mapDirTarget = 90 - fDirTarget
elseif fDirTarget >= 90 and fDirTarget < 180 then
mapDirTarget = 360 - (fDirTarget - 90)
elseif fDirTarget >= 180 and fDirTarget < 270 then
mapDirTarget = 180 + (270 - fDirTarget)
elseif fDirTarget >= 270 and fDirTarget <= 360 then
mapDirTarget = 90 + (360 - fDirTarget)
end if
'get direction between 2 longlat
myDirection = getDirection(StartLong,StartLat,EndLong,EndLat)
'rate for azimuth to ring
fRateRing = getRate_AzimuthToRingWidth(mapDirSource,fRingWidth,myDirection)
'calculate rate by source vs target azimuth --> makin berlawanan smakin bagus
fRateAntDir = getRate_AntDirection(mapDirSource,mapDirTarget)
'calculate rate by target azimuth vs both direction --> makin berlawanan smakin bagus
fRateBothDir = getRate_BothDirection(myDirection,mapDirTarget)
End Sub
if fDirSource >= 0 and fDirSource < 90 then
mapDirSource = 90 - fDirSource
elseif fDirSource >= 90 and fDirSource < 180 then
mapDirSource = 360 - (fDirSource - 90)
elseif fDirSource >= 180 and fDirSource < 270 then
mapDirSource = 180 + (270 - fDirSource)
elseif fDirSource >= 270 and fDirSource <= 360 then
mapDirSource = 90 + (360 - fDirSource)
end if
if fDirTarget >= 0 and fDirTarget < 90 then
mapDirTarget = 90 - fDirTarget
elseif fDirTarget >= 90 and fDirTarget < 180 then
mapDirTarget = 360 - (fDirTarget - 90)
elseif fDirTarget >= 180 and fDirTarget < 270 then
mapDirTarget = 180 + (270 - fDirTarget)
elseif fDirTarget >= 270 and fDirTarget <= 360 then
mapDirTarget = 90 + (360 - fDirTarget)
end if
'get direction between 2 longlat
myDirection = getDirection(StartLong,StartLat,EndLong,EndLat)
'rate for azimuth to ring
fRateRing = getRate_AzimuthToRingWidth(mapDirSource,fRingWidth,myDirection)
'calculate rate by source vs target azimuth --> makin berlawanan smakin bagus
fRateAntDir = getRate_AntDirection(mapDirSource,mapDirTarget)
'calculate rate by target azimuth vs both direction --> makin berlawanan smakin bagus
fRateBothDir = getRate_BothDirection(myDirection,mapDirTarget)
End Sub
Related Functions :
Function getDirection(ByVal StartLong as float,ByVal StartLat as float,ByVal EndLong as float,ByVal EndLat as float) as float
dLon = EndLong - StartLong
Ytmp = Cos(deg2rad(StartLat)) * Sin(deg2rad(EndLat)) - Sin(deg2rad(StartLat)) * Cos(deg2rad(EndLat)) * Cos(deg2rad(dLon))
Xtmp = Sin(deg2rad(dLon)) * Cos(deg2rad(EndLat))
Bearing = aTan2(Ytmp, Xtmp)
AZM = Round(rad2deg(Bearing), 0.1)
If AZM < 0 Then
getDirection = 360 - Abs(AZM)
Else
getDirection = AZM
End If
End Function
Function getRate_AzimuthToRingWidth(ByVal mapDirSource as float,ByVal fRingWidth as float,ByVal myDirection as float) as float
in_range = 0
Rw_start = mapDirSource - (fRingWidth / 2)
Rw_stop = mapDirSource + (fRingWidth / 2)
If (myDirection <= Rw_stop) And (myDirection >= Rw_start) Then
in_range = 1
If myDirection = mapDirSource Then
positionRate = 100
Else
If myDirection > mapDirSource Then
gap_angle = myDirection - mapDirSource
Else
gap_angle = mapDirSource - myDirection
End If
End If
ElseIf ((myDirection - 360) <= Rw_stop) And ((myDirection - 360) >= Rw_start) Then
in_range = 1
If (myDirection - 360) = mapDirSource Then
positionRate = 100
Else
If (myDirection - 360) > mapDirSource Then
gap_angle = (myDirection - 360) - mapDirSource
Else
gap_angle = mapDirSource - (myDirection - 360)
End If
End If
ElseIf ((myDirection + 360) <= Rw_stop) And ((myDirection + 360) >= Rw_start) Then
in_range = 1
If (myDirection + 360) = mapDirSource Then
positionRate = 100
Else
If (myDirection + 360) > mapDirSource Then
gap_angle = (myDirection + 360) - mapDirSource
Else
gap_angle = mapDirSource + (myDirection + 360)
End If
End If
End If
If in_range = True Then
positionRate = (((fRingWidth / 2) - gap_angle) / (fRingWidth / 2)) * 100
Else
positionRate = 0
End If
getRate_AzimuthToRingWidth = positionRate
End Function
Function getRate_BothDirection(ByVal bothDirection as float, ByVal mapDirTarget as float) as float
azsource = deg2rad(bothDirection)
aztarget = deg2rad(mapDirTarget)
cross_2_pi = 0
If (bothDirection >= 0) And (bothDirection < 90) Then
If (mapDirTarget >= 270) And (mapDirTarget < 360) Then
cross_2_pi = 1
on_rad_4 = "target"
End If
ElseIf (mapDirTarget >= 0) And (mapDirTarget < 90) Then
If (bothDirection >= 270) And (bothDirection < 360) Then
cross_2_pi = 1
on_rad_4 = "source"
End If
End If
If cross_2_pi = 1 Then
If on_rad_4 = "source" Then
azsource = azsource - (2 * pi)
ElseIf on_rad_4 = "target" Then
aztarget = aztarget - (2 * pi)
End If
End If
If aztarget > azsource Then
gap_azimuth = aztarget - azsource
ElseIf aztarget < azsource Then
gap_azimuth = azsource - aztarget
ElseIf aztarget = azsource Then
gap_azimuth = 0
End If
If gap_azimuth > pi Then
getRate_BothDirection = ((pi - (gap_azimuth - pi)) / pi) * 100
Else
getRate_BothDirection = (gap_azimuth / pi) * 100
End If
End Function
Function getRate_AntDirection(ByVal mapDirSource as float, ByVal mapDirTarget as float) as float
azsource = deg2rad(mapDirSource)
aztarget = deg2rad(mapDirTarget)
cross_2_pi = 0
If (mapDirSource >= 0) And (mapDirSource < 90) Then
If (mapDirTarget >= 270) And (mapDirTarget < 360) Then
cross_2_pi = 1
on_rad_4 = "target"
End If
ElseIf (mapDirTarget >= 0) And (mapDirTarget < 90) Then
If (mapDirSource >= 270) And (mapDirSource < 360) Then
cross_2_pi = 1
on_rad_4 = "source"
End If
End If
If cross_2_pi = 1 Then
If on_rad_4 = "source" Then
azsource = azsource - (2 * pi)
ElseIf on_rad_4 = "target" Then
aztarget = aztarget - (2 * pi)
End If
End If
If aztarget > azsource Then
gap_azimuth = aztarget - azsource
ElseIf aztarget < azsource Then
gap_azimuth = azsource - aztarget
ElseIf aztarget = azsource Then
gap_azimuth = 0
End If
If gap_azimuth > pi Then
getRate_AntDirection = ((pi - (gap_azimuth - pi)) / pi) * 100
Else
getRate_AntDirection = (gap_azimuth / pi) * 100
End If
End Function
Function deg2rad(ByVal deg As float) as float
deg2rad = deg * pi / 180
End Function
Function rad2deg(ByVal rad As float) as float
rad2deg = rad * 180 / pi
End Function
Function aTan2(ByVal Ytmp As float, ByVal Xtmp As float) as float
If Xtmp > 0 Then
aTan2 = Atn(Ytmp / Xtmp)
ElseIf Xtmp < 0 And Ytmp >= 0 Then
aTan2 = Atn(Ytmp / Xtmp) + pi
ElseIf Xtmp = 0 And Ytmp > 0 Then
aTan2 = pi / 2
ElseIf Xtmp < 0 And Ytmp < 0 Then
aTan2 = Atn(Ytmp / Xtmp) - pi
ElseIf Xtmp = 0 And Ytmp < 0 Then
aTan2 = -pi / 2
End If
End Function
dLon = EndLong - StartLong
Ytmp = Cos(deg2rad(StartLat)) * Sin(deg2rad(EndLat)) - Sin(deg2rad(StartLat)) * Cos(deg2rad(EndLat)) * Cos(deg2rad(dLon))
Xtmp = Sin(deg2rad(dLon)) * Cos(deg2rad(EndLat))
Bearing = aTan2(Ytmp, Xtmp)
AZM = Round(rad2deg(Bearing), 0.1)
If AZM < 0 Then
getDirection = 360 - Abs(AZM)
Else
getDirection = AZM
End If
End Function
Function getRate_AzimuthToRingWidth(ByVal mapDirSource as float,ByVal fRingWidth as float,ByVal myDirection as float) as float
in_range = 0
Rw_start = mapDirSource - (fRingWidth / 2)
Rw_stop = mapDirSource + (fRingWidth / 2)
If (myDirection <= Rw_stop) And (myDirection >= Rw_start) Then
in_range = 1
If myDirection = mapDirSource Then
positionRate = 100
Else
If myDirection > mapDirSource Then
gap_angle = myDirection - mapDirSource
Else
gap_angle = mapDirSource - myDirection
End If
End If
ElseIf ((myDirection - 360) <= Rw_stop) And ((myDirection - 360) >= Rw_start) Then
in_range = 1
If (myDirection - 360) = mapDirSource Then
positionRate = 100
Else
If (myDirection - 360) > mapDirSource Then
gap_angle = (myDirection - 360) - mapDirSource
Else
gap_angle = mapDirSource - (myDirection - 360)
End If
End If
ElseIf ((myDirection + 360) <= Rw_stop) And ((myDirection + 360) >= Rw_start) Then
in_range = 1
If (myDirection + 360) = mapDirSource Then
positionRate = 100
Else
If (myDirection + 360) > mapDirSource Then
gap_angle = (myDirection + 360) - mapDirSource
Else
gap_angle = mapDirSource + (myDirection + 360)
End If
End If
End If
If in_range = True Then
positionRate = (((fRingWidth / 2) - gap_angle) / (fRingWidth / 2)) * 100
Else
positionRate = 0
End If
getRate_AzimuthToRingWidth = positionRate
End Function
Function getRate_BothDirection(ByVal bothDirection as float, ByVal mapDirTarget as float) as float
azsource = deg2rad(bothDirection)
aztarget = deg2rad(mapDirTarget)
cross_2_pi = 0
If (bothDirection >= 0) And (bothDirection < 90) Then
If (mapDirTarget >= 270) And (mapDirTarget < 360) Then
cross_2_pi = 1
on_rad_4 = "target"
End If
ElseIf (mapDirTarget >= 0) And (mapDirTarget < 90) Then
If (bothDirection >= 270) And (bothDirection < 360) Then
cross_2_pi = 1
on_rad_4 = "source"
End If
End If
If cross_2_pi = 1 Then
If on_rad_4 = "source" Then
azsource = azsource - (2 * pi)
ElseIf on_rad_4 = "target" Then
aztarget = aztarget - (2 * pi)
End If
End If
If aztarget > azsource Then
gap_azimuth = aztarget - azsource
ElseIf aztarget < azsource Then
gap_azimuth = azsource - aztarget
ElseIf aztarget = azsource Then
gap_azimuth = 0
End If
If gap_azimuth > pi Then
getRate_BothDirection = ((pi - (gap_azimuth - pi)) / pi) * 100
Else
getRate_BothDirection = (gap_azimuth / pi) * 100
End If
End Function
Function getRate_AntDirection(ByVal mapDirSource as float, ByVal mapDirTarget as float) as float
azsource = deg2rad(mapDirSource)
aztarget = deg2rad(mapDirTarget)
cross_2_pi = 0
If (mapDirSource >= 0) And (mapDirSource < 90) Then
If (mapDirTarget >= 270) And (mapDirTarget < 360) Then
cross_2_pi = 1
on_rad_4 = "target"
End If
ElseIf (mapDirTarget >= 0) And (mapDirTarget < 90) Then
If (mapDirSource >= 270) And (mapDirSource < 360) Then
cross_2_pi = 1
on_rad_4 = "source"
End If
End If
If cross_2_pi = 1 Then
If on_rad_4 = "source" Then
azsource = azsource - (2 * pi)
ElseIf on_rad_4 = "target" Then
aztarget = aztarget - (2 * pi)
End If
End If
If aztarget > azsource Then
gap_azimuth = aztarget - azsource
ElseIf aztarget < azsource Then
gap_azimuth = azsource - aztarget
ElseIf aztarget = azsource Then
gap_azimuth = 0
End If
If gap_azimuth > pi Then
getRate_AntDirection = ((pi - (gap_azimuth - pi)) / pi) * 100
Else
getRate_AntDirection = (gap_azimuth / pi) * 100
End If
End Function
Function deg2rad(ByVal deg As float) as float
deg2rad = deg * pi / 180
End Function
Function rad2deg(ByVal rad As float) as float
rad2deg = rad * 180 / pi
End Function
Function aTan2(ByVal Ytmp As float, ByVal Xtmp As float) as float
If Xtmp > 0 Then
aTan2 = Atn(Ytmp / Xtmp)
ElseIf Xtmp < 0 And Ytmp >= 0 Then
aTan2 = Atn(Ytmp / Xtmp) + pi
ElseIf Xtmp = 0 And Ytmp > 0 Then
aTan2 = pi / 2
ElseIf Xtmp < 0 And Ytmp < 0 Then
aTan2 = Atn(Ytmp / Xtmp) - pi
ElseIf Xtmp = 0 And Ytmp < 0 Then
aTan2 = -pi / 2
End If
End Function

