Android Question CallSub2 Sub not found

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Calling a Public Sub in a class from another class:

B4X:
private Sub touchInShape(aX As Double, aY As Double) As Map
    
    Dim m As Map
    Dim p As TMapPoint = MapUtilities.initPoint(aX, aY)
    Dim tLL As TMapLatLng = PointToLatLng(p)

    m.Initialize

    For Each oKey As Object In fMap.fShapes.Keys
        Dim oItem As Object = fMap.fShapes.Get(oKey)
        If CallSub2(oItem, "PointInShapeX", tLL) Then '<<<<<<<<< error Sub not found here
        'If CallSub2(oItem,"PointInShape", p) Then
            m.Put(oKey, oItem)
        End If
    Next
    Return m
End Sub

This is the code in the other class being called:

B4X:
'return true if type LatLng is in shape
Public Sub PointInShapeX(tLL As TMapLatLng) As Boolean
    
    'to do a quick and simple check first
    Dim BB As TMapBoxLatLng = BoundingBox2(fShape)
    If (tLL.fLat > BB.fLeftTop.fLat) Or (tLL.fLat < BB.fRightBottom.fLat) Or _
        (tLL.fLng > BB.fRightBottom.fLng) Or (tLL.fLng < BB.fLeftTop.fLng) Then
        Return False
    End If
    
'    'http://geomalgorithms.com/a03-_inclusion.html
'    '2012 Dan Sunday
'    '---------------------------------------------

    Dim i As Int
    Dim wn As Int
    Dim iUBound As Int
    Dim tLL1 As TMapLatLng
    Dim tLL2 As TMapLatLng
    
    iUBound = fShape.fLatLng.Size - 1

    For i = 0 To iUBound - 1 '- 1 as we do i + 1
        tLL1 = fShape.fLatLng.Get(i)
        tLL2 = fShape.fLatLng.Get(i + 1)
        If tLL1.flng <= tLL.fLng Then
            If tLL2.flng > tLL.fLng Then
                If IsLeft(tLL1, tLL2, tLL.fLat, tLL.fLng) Then
                    wn = wn + 1
                End If
            End If
        Else
            If tLL2.flng <= tLL.fLng Then
                If IsLeft(tLL1, tLL2, tLL.fLat, tLL.fLng) = False Then
                    wn = wn - 1
                End If
            End If
        End If
    Next
    
    Return wn <> 0
    
End Sub

It compiles fine, but get this error:

cvmap_touchinshape (java line: 1764)
java.lang.Exception: Sub pointinshapex was not found.
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:219)
at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:1082)
at anywheresoftware.b4a.keywords.Common.CallSubNew2(Common.java:1037)
at b4a.sqlitelight1.cvmap._touchinshape(cvmap.java:1764)
at b4a.sqlitelight1.cvmap._fviewtouch_touch(cvmap.java:813)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:213)
at anywheresoftware.b4a.BA$1.run(BA.java:352)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8633)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1133)

When I call another Sub in the same class that has Public Sub PointInShapeX it all runs fine.
That other Sub is very similar and this is the code of that Sub:

B4X:
'return true if point is in shape
Public Sub PointInShape(aPoint As TMapPoint) As Boolean
    
    'https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
    
    'to do a quick and simple check first
    Dim r As B4XRect = BoundingBox(fShape)
    If (aPoint.fX < r.left) Or (aPoint.fX > r.Right) Or (aPoint.fY < r.Top) Or (aPoint.fY > r.Bottom) Then
        Return False
    End If

    Dim bInside As Boolean
    Dim i As Int
    Dim j As Int = fShape.fLatLng.size - 1
    
    For i = 0 To fShape.fLatLng.Size - 1
        Dim pti As TMapPoint = fcvMap.LatLngToPoint(fShape.fLatLng.Get(i))
        Dim ptj As TMapPoint = fcvMap.LatLngToPoint(fShape.fLatLng.Get(j))
        If ((pti.fy > aPoint.fY) <> (ptj.fy > aPoint.fY)) And _
            (aPoint.fX < (ptj.fX - pti.fX) * (aPoint.fY - pti.fY) / (ptj.fy - pti.fY) + pti.fX) Then
            bInside = Not(bInside)
        End If
        j = i
    Next
    
    Return bInside
    
End Sub

Can't understand this at all.
Any ideas?

RBS
 

LucaMs

Expert
Licensed User
Longtime User
B4X:
    For Each oKey As Object In fMap.fShapes.Keys
        Dim oItem As Object = fMap.fShapes.Get(oKey)
        Log(GetType(oItem)) ' <--- add this line
        If CallSub2(oItem, "PointInShapeX", tLL) Then '<<<<<<<<< error Sub not found here
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
B4X:
    For Each oKey As Object In fMap.fShapes.Keys
        Dim oItem As Object = fMap.fShapes.Get(oKey)
        Log(GetType(oItem)) ' <--- add this line
        If CallSub2(oItem, "PointInShapeX", tLL) Then '<<<<<<<<< error Sub not found here
I had to alter the calling Sub a bit to your log as oItem is a class instance:

B4X:
private Sub touchInShape(aX As Double, aY As Double) As Map
    
    Dim m As Map
    Dim str As String

    m.Initialize
    Dim p As TMapPoint = MapUtilities.initPoint(aX, aY)
    Dim tLL As TMapLatLng = PointToLatLng(p)
'    For Each oItem As Object In fMap.fShapes.Values
'        Log(fMap.fShapes.GetKeyAt(i))
'        If CallSub2(oItem,"PointInShape", p) Then
'            l.Add(oItem)
'        End If
'    Next
    For Each oKey As Object In fMap.fShapes.Keys
        Dim oItem As Object = fMap.fShapes.Get(oKey)
        
        str = oKey
        If str = "MapArea" Then
            Dim cMSP As clsMapShapePolygon
            cMSP = oItem
            Log(cMSP.Shape_Data)
        Else
            If str.Contains("Polygon_Line") Then
                Dim cMSL As clsMapShapeLine
                cMSL = oItem
                Log(cMSL.Shape_Data)
            Else
                Dim cMSC As clsMapShapeCircle
                cMSC = oItem
                Log(cMSC.Shape_Data)
            End If
        End If
        
        If CallSub2(oItem, "PointInShapeX", tLL) Then
        'If CallSub2(oItem,"PointInShape", p) Then
            m.Put(oKey, oItem)
        End If
    Next
    Return m
End Sub

The log runs fine, first shape is a circle and the Shape_Data shows fine, in this case an integer number.

RBS
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
It seems to me that oItem is not a module but an object so callSub should not be used.

Better to see the code to understand better
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
It seems to me that oItem is not a module but an object so callSub should not be used.

Better to see the code to understand better
I think I posted all the relevant code.
When I call a different Sub (posted) it runs fine, using the same calling code as in the posted private Sub touchInShape.
This is the code in Main that sets the class instance in the map:

B4X:
        If lstPathOverLay1Points2.Size > 1 Then
            oKey = "Polygon_Line" & mapShapes.Size
            Dim tMSL As TMapShapeLine 'this is a type
            tMSL = MapUtilities.initShapeLine(tLL1,tLL2, xui.Color_ARGB(128,255,0,255), 1dip, oKey)
            Dim cMSL As clsMapShapeLine 'this is a class instance
            cMSL = MapUtilities.instanceShapeLine(cvMap1, tMSL)
            mapPolygonLines.Put(oKey, oKey)
            mapShapes.Put(oKey, cMSL) 'this is the map that will be used in the earlier posted code
            cvMap1.Draw
        End If

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Add a "dummy", "fake" public sub to that class (clsmapshapecircle) and try calling it (comment out the line that raises the exception and write this call there).

Only as a test, of course.

What happens?

Done that and all working perfectly fine.
Drew a polygon and then clicked in it and the log shows fine:

GetType(oItem): b4a.sqlitelight1.clsmapshapecircle
Shape data: 7039
DummyCircle
GetType(oItem): b4a.sqlitelight1.clsmapshapeline
Shape data: Polygon_Line1
DummyLine
GetType(oItem): b4a.sqlitelight1.clsmapshapeline
Shape data: Polygon_Line2
DummyLine
GetType(oItem): b4a.sqlitelight1.clsmapshapeline
Shape data: Polygon_Line3
DummyLine
GetType(oItem): b4a.sqlitelight1.clsmapshapeline
Shape data: Polygon_Line4
DummyLine
GetType(oItem): b4a.sqlitelight1.clsmapshapepolygon
Shape data: MapArea
DummyPolygon

This was the code:

B4X:
private Sub touchInShape(aX As Double, aY As Double) As Map

    Dim m As Map
    Dim str As String

    m.Initialize
    Dim p As TMapPoint = MapUtilities.initPoint(aX, aY)

    For Each oKey As Object In fMap.fShapes.Keys
        Dim oItem As Object = fMap.fShapes.Get(oKey)
        
        Log("GetType(oItem): " & GetType(oItem))
        
        str = oKey
        If str = "MapArea" Then
            Dim cMSP As clsMapShapePolygon
            cMSP = oItem
            Log("Shape data: " & cMSP.Shape_Data)
            CallSub(oItem,"DummyPolygon")
        Else
            If str.Contains("Polygon_Line") Then
                Dim cMSL As clsMapShapeLine
                cMSL = oItem
                Log("Shape data: " & cMSL.Shape_Data)
                CallSub(oItem,"DummyLine")
            Else
                Dim cMSC As clsMapShapeCircle
                cMSC = oItem
                Log("Shape data: " & cMSC.Shape_Data)
                CallSub(oItem,"DummyCircle")
            End If
        End If
        
'        If CallSub2(oItem, "PointIn_ShapeX", tLL) Then


        If CallSub2(oItem,"PointInShape", p) Then
            m.Put(oKey, oItem)
        End If
    Next
    Return m
End Sub

Baffled by this.

RBS
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
This was the code:
I meant to the code you posted in #1.
B4X:
private Sub touchInShape(aX As Double, aY As Double) As Map
    
    Dim m As Map
    Dim p As TMapPoint = MapUtilities.initPoint(aX, aY)
    Dim tLL As TMapLatLng = PointToLatLng(p)

    m.Initialize

    For Each oKey As Object In fMap.fShapes.Keys
        Dim oItem As Object = fMap.fShapes.Get(oKey)
        ''''''  If CallSub2(oItem, "PointInShapeX", tLL) Then '<<<<<<<<< error Sub not found here
CallSub(oItem,"DummyPolygon")
        'If CallSub2(oItem,"PointInShape", p) Then
            m.Put(oKey, oItem)
        '''''  End If
    Next
    Return m
End Sub
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
I meant to the code you posted in #1.
B4X:
private Sub touchInShape(aX As Double, aY As Double) As Map
   
    Dim m As Map
    Dim p As TMapPoint = MapUtilities.initPoint(aX, aY)
    Dim tLL As TMapLatLng = PointToLatLng(p)

    m.Initialize

    For Each oKey As Object In fMap.fShapes.Keys
        Dim oItem As Object = fMap.fShapes.Get(oKey)
        ''''''  If CallSub2(oItem, "PointInShapeX", tLL) Then '<<<<<<<<< error Sub not found here
CallSub(oItem,"DummyPolygon")
        'If CallSub2(oItem,"PointInShape", p) Then
            m.Put(oKey, oItem)
        '''''  End If
    Next
    Return m
End Sub
Don't get that. It will error as there will be the wrong Sub for the wrong class.
DummyPolygon can only be called if oItem is an instance of the polygon class.

RBS

RBS
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Don't get that. It will error as there will be the wrong Sub for the wrong class.
DummyPolygon can only be called if oItem is an instance of the polygon class.

RBS

RBS
I do not understand you. You posted that source, post # 1, highlighting the error, writing a comment:
If CallSub2(oItem, "PointInShapeX", tLL) Then '<<<<<<<<< error Sub not found here
You then made a log to check the type of oItem, which turns out to be
b4a.sqlitelight1.clsmapshapecircle

Now, you have added that Sub DummyPolygon to clsmapshapecircle; call it from that same point of the source, removing that "If CallSub2...".

If this works without problems, it would appear that there was a problem with the name of the other Sub you call (the "original" one).
If, however, even DummyPolygon is not found... we'll talk about it again.
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
I do not understand you. You posted that source, post # 1, highlighting the error, writing a comment:

You then made a log to check the type of oItem, which turns out to be
b4a.sqlitelight1.clsmapshapecircle

Now, you have added that Sub DummyPolygon to clsmapshapecircle; call it from that same point of the source, removing that "If CallSub2...".

If this works without problems, it would appear that there was a problem with the name of the other Sub you call (the "original" one).
If, however, even DummyPolygon is not found... we'll talk about it again.
If I run your last posted code then I get:

GetType(oItem): b4a.sqlitelight1.clsmapshapecircle
cvmap_touchinshape (java line: 1766)
java.lang.Exception: Sub dummypolygon was not found.
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:219)
at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:1082)
at anywheresoftware.b4a.keywords.Common.CallSubNew(Common.java:1029)
at b4a.sqlitelight1.cvmap._touchinshape(cvmap.java:1766)
at b4a.sqlitelight1.cvmap._fviewtouch_touch(cvmap.java:813)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:213)
at anywheresoftware.b4a.BA$1.run(BA.java:352)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8633)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1133)

It is bit complex and watching a football match (Man City v Man United) and that doesn't help.
Will have a better look a bit later.
Thanks in any case for the assistance.

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Perfect, this means that you added sub dummypolygon to a different class module!
What I don't understand is that there is no problem with doing:

If CallSub2(oItem,"PointInShape", p) Then

Even although it is called for the wrong class (eg b4a.sqlitelight1.clsmapshapecircle)

But that there is a problem when I do:

If CallSub2(oItem, "PointIn_ShapeX", tLL) Then

Both PointInShape and PointIn_ShapeX are in the same class, that is b4a.sqlitelight1.clsmapshapepolygon

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
After that test, DummyPolygon, I'm not so sure about that.

Try another test: change the name of the "working sub", PointInShape, to something like "NewPointInShape" (and the calls to it).
They definitely are in the same class!
Will try your suggestion in a bit.

RBS
 
Upvote 0
Top