Kamis, 31 Juli 2014

View Neighbor Dengan Mapbasic

Post yg ini sih intinya mw ngebahas gmn caranya (step2 dan mapbasic code nya) utk menampilkan neighbor baik itu bothway, oneway incoming, dan oneway outgoing, serta undefined neighbor dari suatu cell seperti yg ada di blog saya yg ini. Intinya sih collect data dari table Nbr, trus dibikin deh garis2 relasinya.

Step2nya yg saya ngerti dan saya pke sih gini :
  1. Join table data cell (Data_3G_Cell) dgn Nbr 3G 3G (Nbr_3G3G). Join dilakukan 2x, pertama utk mendapatkan outgoing data (Source Nbr adalah selected object) dan disimpan sementara di qRel1, lalu yg kedua utk mendapatkan incoming data (Target Nbr adalah selected object) dan disimpan sementara di qRel2. Kedua hasil datanya disimpan di table lain, kita kasi nama aja tmpRel.
  2. Looping qRel1 juga qRel2 utk proses pembuatan object antenna dan garis neighbor nya, sesuai dengan style yg sudah kita define.
  3. Create table tmpObj utk object antenna sesuai dgn object yg sudah di compile di Step 2 dan update table tmpRel utk data InOut_Att ambil dari NCell data (SHO_NCell).
  4. Jika Show Undefined = True, maka harus dicari dari table SHO_NCell yg attempt nya tinggi (melebihi threshold) tp tidak ada di tmpRel. Datanya kemudian ditaro di table tmpRel juga.
  5. Final proses penggambaran object antenna dan relasi.
Puyeng yak baca step2 di atas klo pke bahasa sendiri? huehehe.. Mungkin lebih bs ngerti klo liat mapbasic code nya langsung.

Step 1 :
'Outgoing from selected Object
select Source,Target,SHO_Att,RNC_CellID,Longitude,Latitude,Azimuth,"I=xxxxxxxxxxxxx; O=xxxxxxxxxxxxx" "InOut_Att",Data_3G_Cell.Obj "antObj" 
from tmpNbr_3G3G,Data_3G_Cell 
where tmpNbr_3G3G.Source=selObject     'selObject = RNC_CellID object yg diselect dari table Data_3G_Cell
and tmpNbr_3G3G.Target=Data_3G_Cell.RNC_CellID
and Data_3G_Cell.Carrier=sSelectedCarrier     'sSelectedCarrier = carrier dari selObject
into qRel1 noselect

Commit Table qRel1 As myAppDir + "Table\tmpRel.TAB" TYPE NATIVE Charset "WindowsLatin1"
Open Table myAppDir + "Table\tmpRel.TAB" Interactive
sTableRel_tmp = PathToTableName$(myAppDir + "Table\tmpRel.TAB")

'Incoming to selected Object
select Source,Target,SHO_Att,RNC_CellID,Longitude,Latitude,Azimuth,"I=xxxxxxxxxxxxx; O=xxxxxxxxxxxxx" "InOut_Att",Data_3G_Cell.Obj "antObj" 
from tmpNbr_3G3G,Data_3G_Cell 
where tmpNbr_3G3G.Target=selObject     'selObject = RNC_CellID object yg diselect dari table Data_3G_Cell
and tmpNbr_3G3G.Source=Data_3G_Cell.RNC_CellID 
and Data_3G_Cell.Carrier=sSelectedCarrier     'sSelectedCarrier = carrier dari selObject
into qRel2 noselect

Insert Into sTableRel_tmp ( COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8) Select COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8 From qRel2
Commit table sTableRel_tmp

Step 2 :
do while not EOT(qRel1)
inputAnt(iLoop)=qRel1.antObj
ant=inputAnt(iLoop)
sourceId=qRel1.Source
targetId=qRel1.Target
tx=centroidx(ant)
ty=centroidy(ant)

select count(*) from sTableRel_tmp where Source=targetId and Target=sourceId into qBoth noselect
if qBoth.Count > 0 then 'bothway
Create Line into Variable rel (sx,sy) (tx,ty) Pen pPenTargetBoth
antColor=bBrushTargetBoth
else 'outgoing one way
Create Line into Variable rel (sx,sy) (tx,ty) Pen pPenTargetOut
antColor=bBrushTargetOut
end if

close table qBoth
Alter Object inputAnt(iLoop) Info OBJ_INFO_BRUSH, antColor
tmpSourceCell(iLoop)=sourceId
tmpTargetCell(iLoop)=targetId
inputRel(iLoop)=rel
iSelTotalNbr=iSelTotalNbr+1
iLoop=iLoop+1
fetch next from qRel1
loop

do while not EOT(qRel2)
inputAnt(iLoop)=qRel2.antObj
ant=inputAnt(iLoop)
sourceId=qRel2.Source
targetId=qRel2.Target
tx=centroidx(ant)
ty=centroidy(ant)

select count(*) from sTableRel_tmp where Source=targetId and Target=sourceId into qBoth noselect
if qBoth.Count = 0 then
Create Line into Variable rel (sx,sy) (tx,ty) Pen pPenTargetInc
antColor=bBrushTargetInc
Alter Object inputAnt(iLoop) Info OBJ_INFO_BRUSH, antColor
tmpSourceCell(iLoop)=targetId
tmpTargetCell(iLoop)=sourceId
inputRel(iLoop)=rel
iLoop=iLoop+1
end if

close table qBoth
fetch next from qRel2
loop

Step 3 dan 4 :
Create Table tmpObj
(RNC_CellID Char(12))
File myAppDir + "Table\tmpObj.TAB"
Create Map For tmpObj CoordSys Earth
Add Map Window FrontWindow()  Auto Layer tmpObj 

Update sTableRel_tmp Set Obj = CreatePoint(0,0)
Commit table sTableRel_tmp

Set Map Window FrontWindow()  Layer tmpObj Display Off
Set Map Window FrontWindow()  Layer sTableRel_tmp Display Off

for i=1 to (iLoop-1)
insert into tmpObj (RNC_CellID, Obj) values (tmpTargetCell(i),inputAnt(i))

if i > 1 then
select * from sTableRel_tmp where Source=tmpSourceCell(i) and Target=tmpTargetCell(i) into qUpdate noselect
If  TableInfo(qUpdate,8) = 0 Then
close table qUpdate
select * from sTableRel_tmp where Source=tmpTargetCell(i) and Target=tmpSourceCell(i) into qUpdate noselect
end if

update qUpdate set Obj=inputRel(i)
close table qUpdate
end if
next

Commit table sTableRel_tmp
Commit table tmpObj
select * from SHO_NCell where Source=selObject into qNCell1 noselect
select * from SHO_NCell where Target=selObject into qNCell2 noselect

Commit Table qNCell1 As myAppDir + "Table\tmpNCell.TAB" TYPE NATIVE Charset "WindowsLatin1"
Open Table myAppDir + "Table\tmpNCell.TAB" Interactive
sTableNCell_tmp = PathToTableName$(myAppDir + "Table\tmpNCell.TAB")
Insert Into sTableNCell_tmp ( COL1, COL2, COL3) Select COL1, COL2, COL3 From qNCell2
Commit table sTableNCell_tmp

if iShowUndefined=1 then
'alter table add ismatched column
alter table sTableNCell_tmp (add isMatched integer)
commit table sTableNCell_tmp
update sTableNCell_tmp set isMatched=0
commit table sTableNCell_tmp

select * from tmpNCell,tmpRel where tmpNCell.Source=tmpRel.Source and tmpNCell.Target=tmpRel.Target into qUpdate noselect
update qUpdate set isMatched=1
commit table sTableNCell_tmp
close table qUpdate

select * from tmpNCell,tmpRel where tmpNCell.Source=tmpRel.Target and tmpNCell.Target=tmpRel.Source into qUpdate noselect
update qUpdate set isMatched=1
commit table sTableNCell_tmp
close table qUpdate

if sCarrierTarget3G="" then
select Source,Target,SHO_Att,RNC_CellID,Longitude,Latitude,Azimuth,"I=xxxxxxxxxxxxx; O=xxxxxxxxxxxxx" "InOut_Att",Data_3G_Cell.Obj "antObj" 
from tmpNCell,Data_3G_Cell 
where tmpNCell.Source=selObject
and tmpNCell.Target=Data_3G_Cell.RNC_CellID 
and tmpNCell.SHO_Att > fUndefinedAtt 
and tmpNCell.IsMatched=0 
and Data_3G_Cell.Carrier=sSelectedCarrier 
into qUndefinedObj noselect
else
select Source,Target,SHO_Att,RNC_CellID,Longitude,Latitude,Azimuth,"I=xxxxxxxxxxxxx; O=xxxxxxxxxxxxx" "InOut_Att",Data_3G_Cell.Obj "antObj" 
from tmpNCell,Data_3G_Cell 
where tmpNCell.Source=selObject
and tmpNCell.Target=Data_3G_Cell.RNC_CellID 
and tmpNCell.SHO_Att > fUndefinedAtt 
and tmpNCell.IsMatched=0 
and Data_3G_Cell.Carrier=sCarrierTarget3G 
into qUndefinedObj noselect
end if

Insert Into sTableRel_tmp ( COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8) Select COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8 From qUndefinedObj
commit table sTableRel_tmp

fetch first from qUndefinedObj
do while not EOT(qUndefinedObj)
undefinedAnt=qUndefinedObj.antObj
undefinedSCell=qUndefinedObj.Source
undefinedTCell=qUndefinedObj.Target
Alter Object undefinedAnt Info OBJ_INFO_BRUSH, bBrushUndefined
insert into tmpObj (RNC_CellID, Obj) values (undefinedTCell,undefinedAnt)

tx=centroidx(undefinedAnt)
ty=centroidy(undefinedAnt)
Create Line into Variable rel (sx,sy) (tx,ty) Pen pPenUndefined

select * from sTableRel_tmp where Source=undefinedSCell and Target=undefinedTCell into qUpdate noselect
update qUpdate set Obj=rel
close table qUpdate
fetch next from qUndefinedObj
loop

commit table tmpObj
commit table sTableRel_tmp
Close Table qUndefinedObj
end if

'loop table sTableRel_tmp to update InOut_Att
select * from sTableRel_tmp into qLoopRel noselect
fetch first from qLoopRel
do while not EOT(qLoopRel)
NCellSource=qLoopRel.Source
NCellTarget=qLoopRel.Target

'in
select * from sTableNCell_tmp where Source=NCellTarget and Target=NCellSource into qIN noselect
NCellIn="In=" + qIN.SHO_Att

'out
select * from sTableNCell_tmp where Source=NCellSource and Target=NCellTarget into qOUT noselect
NCellOut="Out=" + qOut.SHO_Att

NCellInOut=NCellIn + " ; " + NCellOut

select * from sTableRel_tmp where Source=NCellSource and Target=NCellTarget into qUpdateRel noselect
update qUpdateRel set InOut_Att=NCellInOut
close table qUpdateRel
fetch next from qLoopRel
loop

commit table sTableRel_tmp

Step 5 :
Set Map Window FrontWindow()  Layer tmpObj Display Graphic
Set Map Window FrontWindow()  Layer sTableRel_tmp Display Graphic

Set Map Window FrontWindow()  Layer sTableRel_tmp Label Font ("Arial",256,9,255,16777215) With InOut_Att
Set Map Window FrontWindow()  Layer sTableRel_tmp Label Auto On

Untuk Nbr 3G ke 2G dan Nbr 2G ke 2G jg sama pke step2 di atas, cuma nama table data cell, Nbr, dan NCell nya aja yg di ganti. Mudah2an abis liat mapbasic code utk view Nbr dari step 1 ampe step 5 di atas ga tambah puyeng yak :))))

Selasa, 29 Juli 2014

Ngulik Mapbasic (part-3)

Setelah di part sebelumnya kita nyoba2 create point dan ngedit style object pke mapbasic, skrg iseng2annya coba bikin sectoral view dr data cell. Oiya utk yg ini berkaitan dgn project iseng yg skrg lg digarap di blog TelMi Project ini. Data yg dibutuhin standar nya ya cuma unique name, longitude, latitude dan azimuth. Tapi biar data ini nantinya bisa dipake lebih jauh, maka data cell nya dibikin kayak gini aja :

Struktur table data cell

Sectoral view klo di mapinfo bisa kita dapetin dgn mengkombinasi circle, arc, pline, dan region. Circle untuk initial bentuknya, arc untuk bentuk kipas luarnya dgn lebar sesuai beam width, pline untuk mengubah arc menjadi bentuk kipas, dan region sbg final object nya. Ribet ya? Emang.. hahaha.. btw cara ini jg saya dapet googling koq :p

Mapbasic code nya kayak gini :
circ = CreateCircle(centroXObj, centroYObj, (cellRadius/1.60934))
Create Arc into Variable pie (ObjectGeography(circ, 1), ObjectGeography(circ, 2)) (ObjectGeography(circ, 3),
ObjectGeography(circ, 4)) startDir endDir
pie=converttopline(pie) 
alter Object pie Node Add (centroXObj,centroYObj)
pie=converttoregion(pie)
Alter Object pie Info OBJ_INFO_BRUSH, cellStyleColor

Data cell di import dulu lalu di create point. setelah proses create point baru deh dibikin sectoral view nya dgn mapbasic code seperti di atas. Beberapa variable yg dibutuhkan utk create sectoral view dgn metode di atas yaitu :
  1. CentroXObj dan centroYObj adalah nilai dari centroidX dan centroidY object hasil create point (baca di help mapinfo ttg built in function tsb).
  2. cellRadius adalah radius sectoral yg akan kita buat, dalam satuan Km.
  3. startDir dan endDir utk menentukan lebar sektoral view, nilai ini didapat dari (azimuth + beamWidth/2) dan (azimuth - beamWidth/2). Perlu diingat bahwa sudut 0 pada mapinfo berbeda dengan sudut 0 pada panoramic yg dimulai dari utara sehingga disini perlu proses konversi terlebih dahulu.
  4. cellStyleColor adalah brush yg harus kita define terlebih dahulu.
Hasil dari create sectoral view dari data cell 2G dan 3G dengan multiple carrier nya akan seperti gambar ini :

Hasil create sectoral view

Dari gambar di atas terlihat bahwa untuk 1 site yg sama dengan banyak carrier, sectoral view nya tdk teratur, saling tumpang tindih. Kadang carrier-1 posisi di atas, kadang di bawah. Setelah googling kesana-sini ternyata emg di mapinfo tuh utk 1 table yg sama ga ada ordering object layer. Object di render bukan berdasarkan urutan baris data di table, tp berdasarkan density object tsb. Klo kata yg expert sih gini :

"There is no way to permanently control the draw order of objects within a layer.  Layers are the only unit of draw order. Objects are draw in the order they come back from the spatial index and that is determined by the density of objects in an area, the size of the internal blocks and the implementation of the data source (MapInfo native files, MapInfo data stored in a database such as MapInfo SpatialWare or third party vendors such as Oracle where we have absolutely no say over the order). The order is definitely NOT the order in which the data is created and is not in any way related to the Rowids of the records."

Jadi utk ngakalin tampilannya biar cakep, bisa dibikin table2 yg hanya utk sekedar view aja, itu dipisah utk tiap2 carriernya.
Ampe disini pembahasan ttg object2an nya udahan aja. Postingan berikutnya kita coba bahas ttg gmn mapbasic ini bs ngebantu kita dlm hal keperluan optimasi - khususnya dlm neighboring, yg juga merupakan detil Project TelMi.

Rabu, 23 Juli 2014

Ngulik Mapbasic (part 2)

Utk RF engineer pastinya udh ga asing dgn import hasil export logfile yg formatnya txt, trus jadi .tab di mapinfo, trus di create point utk selanjutnya di thematic. Ataupun ngbikin sektoral pke siteSee atau common. Nah di part ini saya mw coba ngulik lg gmn sih caranya file txt atw xls yg isi nya data2, bisa ke plot di map.

Jadi... (cmiiw lg ya) table di mapinfo itu selain kolom2 utk data, tapi juga ada kolom untuk object/graphic, dgn nama kolom "Obj", tapi kolom ini ga akan muncul atw ga akan keliatan klo kita liat di browser atau kita export table ke csv atw txt. Kolom "Obj" nya sudah ada, cuma isi nya blm tentu ada. Intinya, table mapinfo tidak harus mengandung object, tp harus mengandung data. Contoh, kita import txt file hasil export logfile utk di jadiin tabfile, sampe tahap ini kita baru ngebikin table mapinfo yg berisi data doank. Nah selanjutnya ketika kita create point based on long-lat nya, disitu kita udh mengupdate kolom "Obj" dengan object/graphic utk tiap2 baris data. Jadi... di tiap tabfile, ada data, dan bisa ada object.

Table tanpa object bisa di add ke map window tp tentu nya ga akan muncul apa2. Table dengan object jg bisa ga di munculin di map, dgn dibuka pke "browser" aja misalnya.

Sekarang, gmn caranya utk mengupdate object/graphic dr sebuah table mapinfo? Disini kita pakai sql command update. Contoh table logfileSSV yg sudah diimport tp blm di create point, maka command yg harus kita tulis di mapbasic yaitu :

Create Point :
Create Map For logfileSSV CoordSys Earth  'membuat table logfileSSV menjadi mappable
Add Map Window FrontWindow()  Auto Layer logfileSSV   'add logfileSSV ke current mapper
Set Style Symbol (35,255,6,"Map Symbols",0,0)  'set style untuk objectnya, pakai map symbol
Update logfileSSV Set Obj = CreatePoint(All_Longitude,All_Latitude)  'update posisi object dgn simbol pd baris di atas
Commit Table logfileSSV  'save table

Khusus untuk kasus create point, maka object type nya adalah "point". Ada banyak object type di mapinfo seperti "arc", "rectangle", "line", dll. Untuk lebih jelasnya coba cek link ini

Object Type

Untuk lebih jelas gmn caranya create statement dari masing2 object type di atas, ada koq di mapinfo help file, atau googling lg utk lebih detilnya hehe..

Udah clear kan ya ttg knp table bs muncul di map window.. Nah sebelum ngulik lebih dalem gmn cara bikin2 object ada baiknya mundur sedikit utk mengetahui hal2 yg sering dipake dlm proses bikin object ini, yaitu Pen dan Brush.

Klo dari mapinfo help file :

Pen Clause : Specifies a line style for graphic objects
Brush Clause : Specifies a fill style for graphic objects

Alter Object :
Sub EditObject
     select * from DataCell where Cellname="10000_Cell-1" into qUpdate
     update qUpdate set Obj = AlterStyle(Obj)
     commit table DataCell 
End Sub

Function AlterStyle(ByVal oCellObj As Object) As Object
     Dim bStyle as brush
     Dim pStyle as pen

     bStyle = MakeBrush(2,16711680,16777215)
     pStyle = MakePen(2,3,16711680)

     Alter Object oCellObj Info OBJ_INFO_PEN, pStyle 
     Alter Object oCellObj Info OBJ_INFO_BRUSH, bStyle 

     AlterStyle = oCellObj 
End Function

Berarti sekilas tentang object udh kelar ya. Next nya bahas tentang cara make sector dari data gcell deh ya.

Selasa, 22 Juli 2014

Ngulik Mapbasic (part 1)

Mapbasic? apaan lagi tuh? Pertanyaan yg sama ketika beberapa waktu yg lalu saya dapet request bikin automatic Drive Test reporting tool, dimana kebanyakan scope kerjanya pake mapinfo. Jadi awalnya gini, saya diminta tulung utk speed up progress DT report dgn ngbikin automasi reportnya. Klo OSS scope sih kebaca ya, paling cuma sebatas maen di database, query, ama macro doank. Nah klo report DT kan kan pke mapinfo utk ngeplot2 dan ngethematic hasil DT nya, gmn?? Trus kata salah satu PM bilang, pke mapbasic bro. Hmmm belajar ilmu baru nih, woke lanjutttt.

Jadi, cmiiw ya.. mapbasic itu kaya macro di excel lah.. kita bikin coding sendiri, pke bahasa basic jg, nantinya bisa jadi tool di mapinfo. Kaya MIPT, SNT, common, siteSee, ya itu tool tambahan di mapinfo yg dibikin pke mapbasic. 

Editor mapbasic nya pke apa? Bisa pke mapbasic software itu sendiri (tapi asli dah klo pke ini jelek banget, bikin sakit mata hahaha. Lagipula klo ngedit pke mapbasic software maksimal file size nya cuma 64KB), atau pke text editor yg lainnya. Klo saya sih pke notepad++, enak liatnya, trus bisa di setting language nya pula. Compile nya ya tetep pke software mapbasic. Free download mapbasic disini

Klo yg baru nyoba2 ngulik macro excel kan ada fitur record macro nya tuh, nah klo ini gmn? Tenang, mapbasic jg ada fitur yg mirip2, tapi ngga ngerecord, cuma nunjukin mapbasic code dari setiap aktifitas kita di mapinfo. Nantinya tinggal copy paste ama edit2 dikit deh utk keperluan tool kita.

Munculin mapbasic window di mapinfo : Option -> Show Mapbasic Window

Empty Mapbasic Window

Nah klo udh muncul mapbasic window nya, tiap aktifitas kita di map akan ke translate jd mapbasic code. Mw itu create point, ngethematic, show layer, dll.

Sample Mapbasic Code

Dari gambar di atas, contoh simple mapbasic code untuk meng-off-kan display dari suatu layer, ama ngeganti style layer. Oiya, untuk "31678264" itu adalah window id dari map yg dimunculkan, ganti aja pake FrontWindow(). Dan untuk Layer 1, Layer 3, dll, itu bisa diganti langsung ama nama layer nya, misal jadi "Set Map Window FrontWindow()  Layer Data_3G_Cell_F3 Display Off"

Udh mulai gatel pengen ngulik? huehehe... di link ini ada beberapa contoh mapbasic code juga tips n trik yg bisa dipake utk belajar, mangga di download aja dulu sambil nunggu part 2 nya.

Senin, 21 Juli 2014

3G to 3G Neighbor Analyzer

Iseng2an yg kedua ini gara2 dulu waktu masih OSS ngebet banget pengen ke PLO 3G. Waktu dulu liat2 tmn yg PLO sih banyak kerjaannya create2 neighbor utk newsite, modalnya pke mapinfo, klak klik klak klik source target nya. Klo newsite nya cuma 3-4 sih gpp ya.. tp klo ampe puluhan kan puyeng juga tuh. Udh deh iseng bikin automatic create neighbor nya. 

Awalnya sih krn ini untuk keperluan newsite, yg mana waktu nyiapin neighbor nya si site nya blm tentu udh OA, jadi prediksinya cuma berdasarkan konfigurasi jarak dan azimuth. Nah trus dikembangin lg ampe yg versi terakhir ini (v.9) diperhitungkan juga SHO Attempt nya (barangkali nanti bakal dipakai di project MS).

3G-3G Neighbor Analyzer

Sederhananya, ada 5 point yang dihitung dalam prediksi neighbor ini, sesuai ama capture di atas :
  1. SHO Attempt
  2. Target to Ring Width : Posisi target di area ring width / search beam nya si source (defaultnya 270 deg).
  3. Azimuth Target to Both Direction : Point A pada gambar di bawah. Semakin mendekati 0 maka semakin besar nilai bobot nya.
  4. Azimuth Target to Azimuth Source : Point B pada gambar di bawah. Semakin mendekati 0 maka semakin besar nilai bobot nya.
  5. Target distance from Source.

Detail Kalkulasi 

Fungsi paling penting yg dipake di tool ini yaitu hitung jarak dan sudut dari 2 titik. Banyak sih di google, tinggal edit2 dikit dan diaplikasikan saja. Tapi untuk yg males googling dan edit2 lagi, berikut ini codingnya dalam bahasa basic (tinggal copy paste aja ke VBA access)

VBA nya kayak gini :
Option Compare Database
Const pi = 3.14159265358979

Function getDistance(lat1 As Double, lon1 As Double, lat2 As Double, lon2 As Double, unit As String)
  Dim theta As Double, dist As Double
  theta = lon1 - lon2
  dist = Sin(deg2rad(lat1)) * Sin(deg2rad(lat2)) + Cos(deg2rad(lat1)) * Cos(deg2rad(lat2)) * Cos(deg2rad(theta))

  dist = acos(dist)
  dist = rad2deg(dist)
  getDistance = dist * 60 * 1.1515
  Select Case UCase(unit)
    Case "K"
      getDistance = getDistance * 1.609344
    Case "N"
      getDistance = getDistance * 0.8684
  End Select
End Function


Function getAzimuth(Start_PT_Lat As Double, Start_PT_Long As Double, _
                    End_PT_Lat As Double, End_PT_Long As Double)
        
    Dim rStart_PT_Lat As Double
    Dim rEnd_PT_Lat As Double
    Dim Bearing As Double, dLon  As Double
    Dim x As Double, y As Double
    Dim AZM As Double
    
    dLon = End_PT_Long - Start_PT_Long
    
    y = Cos(deg2rad(Start_PT_Lat)) * Sin(deg2rad(End_PT_Lat)) - Sin(deg2rad(Start_PT_Lat)) * Cos(deg2rad(End_PT_Lat)) * Cos(deg2rad(dLon))
    x = Sin(deg2rad(dLon)) * Cos(deg2rad(End_PT_Lat))
    
    Bearing = aTan2(y, x)
    
    AZM = Round(rad2deg(Bearing), 0.1)
    If AZM < 0 Then
            getAzimuth = 360 - Abs(AZM)
    Else
            getAzimuth = AZM
    End If
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
':::  this function get the arccos function from arctan function    :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Function acos(rad As Double)
  If Abs(rad) <> 1 Then
    acos = pi / 2 - Atn(rad / Sqr(1 - rad * rad))
  ElseIf rad = -1 Then
    acos = pi
  End If
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
':::  this function converts decimal degrees to radians             :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Function deg2rad(deg As Double)
    deg2rad = CDbl(deg * pi / 180)
End Function

'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
':::  this function converts radians to decimal degrees             :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Function rad2deg(rad As Double)
    rad2deg = CDbl(rad * 180 / pi)
End Function

Function aTan2(y As Double, x As Double)
    If x > 0 Then
        aTan2 = Atn(y / x)
    ElseIf x < 0 And y >= 0 Then
        aTan2 = Atn(y / x) + pi
    ElseIf x = 0 And y > 0 Then
        aTan2 = pi / 2
    ElseIf x < 0 And y < 0 Then
        aTan2 = Atn(y / x) - pi
    ElseIf x = 0 And y < 0 Then
        aTan2 = -pi / 2
    End If
End Function

Atau kalau mau yg tinggal pake, download aja 3G-3G Neighbor Analyzer disini :D

Untuk skrg sih tool ini lg dikembangin ke mapbasic, jadi hasil prediksinya bisa keliatan langsung di mapinfo, plus banyak lg fitur2 standar seperti view/add/delete neighbor, dan fitur lainnya seperti overshooting search, touchdown TP/TA, dll. Untuk yg versi mapbasic bahas di posting lainnya aja kali ya.

Huawei Dump Extractor

Huawei Dump Extractor inilah yg menjadi awal mula keisengan disamping kerjaan rutin sebagai engineer telco. Gara2nya? koq bisa? berawal dari beli laptop baru, install W7 64 bit (taun 2010 W7 64 blm terlalu populer), ternyata hw dump extractor yg dikasi ama org huawei nya (dulu tool nya berupa file xls dgn macro di dalemnya) gak bisa dipake. Nah loh.. mw edit2 ternyata diprotect. Trus kerja gmn donk? Daripada puyeng akhirnya nyoba2 bikin extractor sendiri. Eh bisa ternyata huehehehe.

Pertama kali disebar ke tmn2 se-project di taun 2010, masih standar. Cuma bs extract to mdb dan xls doank, itupun parameter2 switchnya masi nyatu di satu field dan proses data ditaro di RAM (klo laptop lelet dan mw extract banyak RNC/BSC bisa hang). Dan skrg versi yg terakhir (v.17.8) udh bs pecah2in parameter switch, proses data ga pke RAM lg (thanks to Ambia utk ide no ram usage ini), compare dump, dan extract dump utk LTE.

Sekilas preview nya :

Extract to mdb

Compare dump

Export to xls


Proses extractnya sih sederhananya kaya gini: 
SET GTRXCHAN:TRXID=1170, CHNO=1, CHTYPE=TCHFR, TSPRIORITY=0, GPRSCHPRI=EGPRSNORCH;

String sebelum tanda ":" (pd contoh yaitu SET GTRXCHAN) akan dijadikan nama table. Disini tool akan mengecek dulu apakah table sudah ada atau belum, jika belum maka akan generate sql command untuk create table, jika sudah ada maka akan generate command untuk insert.

Setelah itu tool akan memecah baris tersisa dengan delimiter "," sehingga didapatkan nama2 field dan value nya. Pada case khusus jika ada parameter switch dimana value nya harus dipecah2 jika ketemu delimiter "&". Untuk menentukan field data type nya ditentukan dari value nya. Jika isnumeric maka langsung saja as double, lainnya text. 

Proses pembentukan sql command ini di looping terus hingga baris terakhir, dan disimpan di file lain berextensi .sql. Setelah selesai mengcompile sql command nya lalu dijalankan sql command pada file .sql tersebut sehingga terbentuk database .mdb.

Emang sih.... proses extract string nya ga canggih kaya pake regex. Maklum, ga ngerti yg bgituan, bukan jebolan programming juga, tp setidaknya masi bisa lah dipake :D

Bagi yg mungkin butuh tool simple ini bisa download aja disini