• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

FSXA Problem with SBuilderX importing shapefiles

arno

Administrator
Staff member
FSDevConf team
Resource contributor
Messages
32,883
Country
netherlands
Hi,

I have a problem with SBuilderX not importing my shapefiles correctly. See the attached screenshots. The source shapefile has LOD10 squares, but they import as triangles into SBuilderX. Has anybody seen this problem before? I have also attached my shapefiles as a zip file in case somebody wants to test if they have the same problem.
 

Attachments

  • Image2010-04-16 2123.34.775.jpg
    Image2010-04-16 2123.34.775.jpg
    76.1 KB · Views: 570
  • Image2010-04-16 2123.49.263.jpg
    Image2010-04-16 2123.49.263.jpg
    78.8 KB · Views: 529
  • excl_DR.zip
    3.4 KB · Views: 313

GHD

Messages
12,243
Country
england
I think that SBX requires that all polygons be closed, ie. the last point should be the same as the first.
 

hcornea

Resource contributor
Messages
2,388
Country
australia
That sounds right ... I've only imported vector lines and the odd multi-point polygon ... but do remember something about it not being complete.
 

arno

Administrator
Staff member
FSDevConf team
Resource contributor
Messages
32,883
Country
netherlands
Hi,

Let me check that. It is weird that two GIS programs can edit and display this shapefile correctly though. Why would SBuilderX ignore the last vertex if it is not the same as the first? The second to last is also not the same as the first...
 

arno

Administrator
Staff member
FSDevConf team
Resource contributor
Messages
32,883
Country
netherlands
Hi,

I indeed see that the squares have "only" four vertices each. Let me see if I can find a way to add the fifth....
 

GHD

Messages
12,243
Country
england
Why would SBuilderX ignore the last vertex if it is not the same as the first? The second to last is also not the same as the first...

I am not Luis, but I think that it assumes that the last vertex is the same as the first so doesn't need to read it.

BTW Bln2Shp has the same requirement.
 

arno

Administrator
Staff member
FSDevConf team
Resource contributor
Messages
32,883
Country
netherlands
Hi,

I have send Luis an email already to ask if this could indeed be the issue. Let's wait and see what the answer is.
 

rhumbaflappy

Administrator
Staff member
Resource contributor
Messages
5,945
Country
us-wisconsin
Hi Arno.

GlobalMapper, and SAGA also read your shp files correctly. I think they are read allright by SBuilderX, but then converted to it's internal format, and changed before display. Exporting them confirms SBuilder has changed them.

Dick
 

Luis_Sá

Resource contributor
Messages
326
Country
portugal
Dear Friends,

I receive this question directly from Arno and will try to answer here. I would like to say that I have very little time for SBuilderX as, from last October, I have new responsibilities at my University that take most of my free time. Here is what I can say:

1 - the import/append function of shape files use the very well known library called shapelib.dll

2 - the first and the last point of a polygon should be the same. See this:

The following are important notes about Polygon shapes.
The rings are closed (the first and last vertex of a ring MUST be the same).


taken from the ESRI definition as per figure 2 of this document:

http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf

3 - SBuilderX is not as robust as it could because it simply assumes that, when reading polygons, the last point is to ignore. It could, as, may be, GIS programmes do, test if the last point is different from the 1st and, if so, take it.

4 - In order to implement this I add to modify the routine called AppendSHPPolys shown below. I think I had to change 4 lines that contain NV (name of the variable that holds the Number of Vertices) such as:

ReDim X(NV - 1) and
N2 = NV -1

and then make the test for identical end points. However as you could see, the horrible internal structure of SBuilderX to store "polygons with holes" make me think if that is as simple as I am thinking.

I wonder if reading the files and exporting again within a good GIS programme will resolve the problem. I do not expect a good GIS programme not to duplicate the end points as the standard tells them to do.

Kind Regards,

Luis


Code:
    Private Sub AppendSHPPolys(ByVal filename As String, ByVal NoOfItems As Integer, ByVal IsZ As Boolean)

        Dim myAltitudes() As Double
        Dim myColors() As Color
        Dim myNames() As String
        Dim myGuids() As String
        Dim myTypes() As String

        Dim A As String

        Dim hdbf As Integer
        Dim recCount As Integer
        Dim N, N1, N2, NV, K, J, JK, I, M, NP As Integer
        Dim FieldTypes() As DBFFieldType
        Dim fname As String = "12345678901"
        Dim fieldWidth As Integer
        Dim numDecimals As Integer

        ' open the dbase file
        hdbf = DBFOpen(filename, "rb")
        recCount = DBFGetRecordCount(hdbf)
        NoOfFields = DBFGetFieldCount(hdbf)

        If recCount <> NoOfItems Then
            MsgBox("SBuilderX can not read the database Shapefile!", MsgBoxStyle.Exclamation)
            DBFClose(hdbf)
            Exit Sub
        End If

        ReDim FieldNames(NoOfFields - 1)
        ReDim FieldTypes(NoOfFields - 1)


        Dim TypeField As Integer = -1  ' added because of Luis Feliz - type for traffic lines was lost!

        For N = 0 To NoOfFields - 1
            FieldTypes(N) = DBFGetFieldInfo(hdbf, N, fname, fieldWidth, numDecimals)
            FieldNames(N) = Left(fname, InStr(fname, vbNullChar) - 1)
            If FieldNames(N) = "Type" Then TypeField = N
        Next N

        frmSHPPoly.ShowDialog()
        ' *********************

        If ShapePolyCancel Then
            DBFClose(hdbf)
            Exit Sub
        End If

        If ShapePolyNameField > 0 Then
            If FieldTypes(ShapePolyNameField - 1) <> DBFFieldType.FTString Then
                A = "Field """ & FieldNames(ShapePolyNameField - 1) & """ is not a string and will be ignored!"
                ShapePolyNameField = 0
                MsgBox(A, MsgBoxStyle.Exclamation)
            End If
        End If

        If ShapePolyGuidField > 0 Then
            If FieldTypes(ShapePolyGuidField - 1) <> DBFFieldType.FTString Then
                A = "Field """ & FieldNames(ShapePolyGuidField - 1) & """ is not a string and will be ignored!"
                ShapePolyGuidField = 0
                MsgBox(A, MsgBoxStyle.Exclamation)
            End If
        End If

        If IsZ Then   ' after scott
            If ShapePolyAltitudeField > 1 Then
                If FieldTypes(ShapePolyAltitudeField - 2) <> DBFFieldType.FTDouble Then
                    A = "Field """ & FieldNames(ShapePolyAltitudeField - 2) & """ is not a double precision number and will be ignored!"
                    ShapePolyAltitudeField = 0
                    MsgBox(A, MsgBoxStyle.Exclamation)
                End If
            End If
        Else
            If ShapePolyAltitudeField > 0 Then
                If FieldTypes(ShapePolyAltitudeField - 1) <> DBFFieldType.FTDouble Then
                    A = "Field """ & FieldNames(ShapePolyAltitudeField - 1) & """ is not a double precision number and will be ignored!"
                    ShapePolyAltitudeField = 0
                    MsgBox(A, MsgBoxStyle.Exclamation)
                End If
            End If

        End If

        If ShapePolyColorField > 0 Then
            If FieldTypes(ShapePolyColorField - 1) <> DBFFieldType.FTInteger Then
                A = "Field """ & FieldNames(ShapePolyColorField - 1) & """ is not a integer number and will be ignored!"
                ShapePolyColorField = 0
                MsgBox(A, MsgBoxStyle.Exclamation)
            End If
        End If

        ReDim myAltitudes(NoOfItems - 1)
        ReDim myColors(NoOfItems - 1)
        ReDim myNames(NoOfItems - 1)
        ReDim myGuids(NoOfItems - 1)
        ReDim myTypes(NoOfItems - 1)

        For N = 0 To NoOfItems - 1

            If ShapePolyNameField = 0 Then
                myNames(N) = ShapePolyName
            Else
                If (DBFIsAttributeNULL(hdbf, N, ShapePolyNameField - 1) = 0) Then
                    myNames(N) = DBFReadStringAttribute(hdbf, N, ShapePolyNameField - 1)
                Else
                    myNames(N) = ""
                End If
            End If

            If ShapePolyGuidField = 0 Then
                myGuids(N) = ShapePolyGuid
            Else
                If (DBFIsAttributeNULL(hdbf, N, ShapePolyGuidField - 1) = 0) Then
                    myGuids(N) = DBFReadStringAttribute(hdbf, N, ShapePolyGuidField - 1)
                Else
                    myGuids(N) = ShapePolyGuid
                End If
            End If

            Try
                myTypes(N) = DBFReadStringAttribute(hdbf, N, TypeField)
                If myTypes(N) = "" Then
                    myTypes(N) = GetPolyTypeFromGuid(myGuids(N))
                End If
            Catch ex As Exception
                myTypes(N) = GetPolyTypeFromGuid(myGuids(N))
            End Try


            If ShapePolyColorField = 0 Then
                myColors(N) = ShapePolyColor
            Else
                If (DBFIsAttributeNULL(hdbf, N, ShapePolyColorField - 1) = 0) Then  ''''
                    myColors(N) = Color.FromArgb(CInt(DBFReadStringAttribute(hdbf, N, ShapePolyColorField - 1)))
                Else
                    myColors(N) = ShapePolyColor
                End If
            End If

            If IsZ Then     ' after scott
                If ShapePolyAltitudeField = 0 Then
                    myAltitudes(N) = ShapePolyAltitude
                ElseIf ShapePolyAltitudeField > 1 Then
                    If (DBFIsAttributeNULL(hdbf, N, ShapePolyAltitudeField - 2) = 0) Then
                        myAltitudes(N) = DBFReadStringAttribute(hdbf, N, ShapePolyAltitudeField - 2)
                    Else
                        myAltitudes(N) = ShapePolyAltitude
                    End If
                End If
            Else
                If ShapePolyAltitudeField = 0 Then
                    myAltitudes(N) = ShapePolyAltitude
                ElseIf ShapePolyAltitudeField > 0 Then
                    If (DBFIsAttributeNULL(hdbf, N, ShapePolyAltitudeField - 1) = 0) Then
                        myAltitudes(N) = DBFReadStringAttribute(hdbf, N, ShapePolyAltitudeField - 1)
                    Else
                        myAltitudes(N) = ShapePolyAltitude
                    End If
                End If
            End If


        Next

        ' close the dbase
        DBFClose(hdbf)

        Dim shpObj As SHPObject
        Dim pShpObj As IntPtr
        Dim hShp As Integer
        Dim X() As Double
        Dim Y() As Double
        Dim Z() As Double
        Dim P() As Integer

        hShp = SHPOpen(filename, "rb")

        ' test SHPReadObject on the shape
        K = NoOfPolys 'counts number of polygons

        ReDim Preserve Polys(K + 100)

        For N = 0 To NoOfItems - 1
            pShpObj = SHPReadObject(hShp, N)
            shpObj = Marshal.PtrToStructure(pShpObj, GetType(SHPObject))
            NV = shpObj.nVertices
            'MsgBox("Vertices = " & NV)
            ReDim X(NV - 1)
            Marshal.Copy(shpObj.padfX, X, 0, NV)
            ReDim Y(NV - 1)
            Marshal.Copy(shpObj.padfY, Y, 0, NV)
            If IsZ And ShapePolyAltitudeField = 1 Then
                ReDim Z(NV - 1)
                Marshal.Copy(shpObj.padfZ, Z, 0, NV)
            Else
                ReDim Z(0)
            End If
            NP = shpObj.nParts
            ReDim P(NP - 1)
            If NP > 1 Then
                Marshal.Copy(shpObj.panPartStart, P, 0, NP)
            End If

            For J = 1 To NP
                K = K + 1
                Polys(K).Name = myNames(N)
                Polys(K).Color = myColors(N)
                Polys(K).Guid = myGuids(N)
                Polys(K).Type = myTypes(N)
                If NP = 1 Then
                    ReDim Polys(K).Childs(0)
                    Polys(K).NoOfChilds = 0
                    N1 = 0
                    N2 = NV - 1
                Else
                    If J = 1 Then   ' first
                        ReDim Polys(K).Childs(NP - 1)
                        Polys(K).NoOfChilds = NP - 1
                        For I = 1 To NP - 1
                            Polys(K).Childs(I) = K + I
                        Next
                        N1 = 0
                        N2 = P(1) - 1
                        JK = K
                    ElseIf J = NP Then  ' last
                        ReDim Polys(K).Childs(0)
                        Polys(K).NoOfChilds = -JK
                        N1 = P(J - 1)
                        N2 = NV - 1
                    Else ' others
                        ReDim Polys(K).Childs(0)
                        Polys(K).NoOfChilds = -JK
                        N1 = P(J - 1)
                        N2 = P(J) - 1
                    End If
                End If

                ReDim Polys(K).GPoints(N2 - N1)
                Polys(K).NoOfPoints = N2 - N1
                For I = N1 To N2 - 1
                    M = I - N1 + 1
                    Polys(K).GPoints(M).lon = X(I)
                    Polys(K).GPoints(M).lat = Y(I)
                    If IsZ And ShapePolyAltitudeField = 1 Then
                        Polys(K).GPoints(M).alt = Z(I)
                    Else
                        Polys(K).GPoints(M).alt = myAltitudes(N)
                    End If
                Next
                AddLatLonToPoly(K)

                If K = NoOfPolys + 100 Then
                    ReDim Preserve Polys(NoOfPolys + 1000)
                End If
                If K = NoOfPolys + 1000 Then
                    ReDim Preserve Polys(NoOfPolys + 10000)
                End If
                If K = NoOfPolys + 10000 Then
                    ReDim Preserve Polys(NoOfPolys + 100000)
                End If
                If K = NoOfPolys + 100000 Then
                    ReDim Preserve Polys(NoOfPolys + 1000000)
                End If
            Next

            SHPDestroyObject(pShpObj)

        Next

        'K is total and final number of polys

        ReDim Preserve Polys(K)
        NoOfPolys = K

        SHPClose(hShp)

    End Sub
 

arno

Administrator
Staff member
FSDevConf team
Resource contributor
Messages
32,883
Country
netherlands
Hi Luis,

Thanks for checking. I will try some other GIS program and see if importing and exporting them works. I made the files with QGIS and already tried to export them with fGIS, but those two seem to be happy with the current file. I'll try some other tools.
 

Luis_Sá

Resource contributor
Messages
326
Country
portugal
Hi Luis,

Thanks for checking. I will try some other GIS program and see if importing and exporting them works. I made the files with QGIS and already tried to export them with fGIS, but those two seem to be happy with the current file. I'll try some other tools.

Hi Arno,

It seems strange to me that GIS tools export (save) Shape files without repeating the 1st point of a polygon! Or have I misread the standard? Please inform us about your findings.

Regards, Luis
 

arno

Administrator
Staff member
FSDevConf team
Resource contributor
Messages
32,883
Country
netherlands
Hi Luis,

If I read the specification I think you implementation is correct, although it would of course be nice if the SHP reader was more flexible :).

I have "solved" the issue in the end by optimizing the shapes in QGIS and then exporting them again. Afterwards the rings were closed as they should be.
 

Kelvin Richardson

Resource contributor
Messages
152
Country
newzealand
Hi Luis,

If I read the specification I think you implementation is correct, although it would of course be nice if the SHP reader was more flexible :).

I have "solved" the issue in the end by optimizing the shapes in QGIS and then exporting them again. Afterwards the rings were closed as they should be.

Hi Arno,

I realize this thread is old but I am revisiting Sbuilder and having the same issue with Sbuilder reading shapefiles out of QGIS. Can you tell me what you did to "optimize" the shapefiles within QGIS?

Thanks
Kelvin
 

arno

Administrator
Staff member
FSDevConf team
Resource contributor
Messages
32,883
Country
netherlands
Owww, that's a long time ago. I don't fully remember what I did back then. But I think I used the tools from Vector -> Geometry Tools -> Check Validity.
 
Top