ThinkGeo.com    |     Documentation    |     Premium Support

System.ArgumentException: The format of the well known binary is incorrect in 6.0.345.0 dlls

     Hi Guys,


 My TilePreCacher was working fine with dlls version 6.0.260.0 and now throws the following exception:


System.ArgumentException: The format of the well known binary is incorrect.

Nombre del parámetro: wellKnownBinary ---> System.ArgumentException: 24413: Not valid because of two overlapping edges in curve (1).

en ThinkGeo.MapSuite.Core.BaseShape.CreateShapeFromWellKnownData(Byte[] wellKnownBinary)

--- Fin del seguimiento de la pila de la excepción interna ---

en ThinkGeo.MapSuite.Core.BaseShape.CreateShapeFromWellKnownData(Byte[] wellKnownBinary)

en ThinkGeo.MapSuite.Core.Feature.GetShape()

en ThinkGeo.MapSuite.Core.LineStyle.SiE=(RectangleShape fmM=, IEnumerable`1 f2M=)

en ThinkGeo.MapSuite.Core.LineStyle.DrawCore(IEnumerable`1 features, GeoCanvas canvas, Collection`1 labelsInThisLayer, Collection`1 labelsInAllLayers)

en ThinkGeo.MapSuite.Core.Style.Draw(IEnumerable`1 features, GeoCanvas canvas, Collection`1 labelsInThisLayer, Collection`1 labelsInAllLayers)

en ThinkGeo.MapSuite.Core.ZoomLevel.DrawCore(GeoCanvas canvas, IEnumerable`1 features, Collection`1 currentLayerLabels, Collection`1 allLayerLabels)

en ThinkGeo.MapSuite.Core.ZoomLevel.Draw(GeoCanvas canvas, IEnumerable`1 features, Collection`1 currentLayerLabels, Collection`1 allLayerLabels)

en ThinkGeo.MapSuite.Core.ShapeFileFeatureLayer.ZlU=(GeoCanvas Z1U=, RectangleShape aFU=, Collection`1 aVU=, ZoomLevel alU=, Collection`1 a1U=, Collection`1 bFU=, ShapeFileFeatureSource bVU=, Collection`1 blU=, Collection`1 b1U=)

en ThinkGeo.MapSuite.Core.ShapeFileFeatureLayer.WVU=(GeoCanvas WlU=, RectangleShape W1U=, Collection`1 XFU=, ZoomLevel XVU=, Collection`1 XlU=, ShapeFileFeatureSource X1U=, Collection`1 YFU=, Collection`1 YVU=)

en ThinkGeo.MapSuite.Core.ShapeFileFeatureLayer.DrawCore(GeoCanvas canvas, Collection`1 labelsInAllLayers)

en ThinkGeo.MapSuite.Core.Layer.Draw(GeoCanvas canvas, Collection`1 labelsInAllLayers)

en TilePreCacherIssueDemo.Module1.Main() en Z:\Documents\Mis Documentos\Visual Studio Projects\TilePreCacherIssueDemo\TilePreCacherIssueDemo\Module1.vb:línea 39


 You can download the refered shape file from here: dl.dropboxusercontent.com/u/6792052/GebcoOneBathyA4.rar


 And this is the source I used:


 Imports System.Collections.ObjectModel


Imports ThinkGeo.MapSuite.Core


Imports ThinkGeo.MapSuite.WpfDesktopEdition


 


Module Module1


 


  Sub Main()


    Dim ZoomLevelIdx As Integer = 13


    Dim cacheDirectory As String = ".\TileCache"


    Dim cacheId As String = "WorldMapOverlay"


    Dim ZoomLevelSet As New ZoomLevelSet


    Dim mapUnit As GeographyUnit = GeographyUnit.DecimalDegree


 


    Dim GebcoOneBathymetricLayer As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(".\GebcoOneBathyA4.shp", ShapeFileReadWriteMode.ReadOnly)


    GebcoOneBathymetricLayer.ZoomLevelSet.ZoomLevel08.DefaultLineStyle = New LineStyle(New GeoPen(GeoColor.SimpleColors.Silver, 1))


    GebcoOneBathymetricLayer.ZoomLevelSet.ZoomLevel08.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level15


    GebcoOneBathymetricLayer.WrappingExtent = New RectangleShape(-180, 90, 180, -90)


    GebcoOneBathymetricLayer.WrappingMode = WrappingMode.WrapDateline


 


    'Create a tile cache object with the cache directory and cache id.


    Dim tileCache As New FileBitmapTileCache(cacheDirectory, cacheId)


    tileCache.ImageFormat = TileImageFormat.Png


    tileCache.TileMatrix.Scale = ZoomLevelSet.GetZoomLevels(ZoomLevelIdx).Scale


    tileCache.TileMatrix.BoundingBox = New RectangleShape(-100000000, 100000000, 100000000, -100000000)


 


    Dim cell As New TileMatrixCell(694, 4330, New RectangleShape(10.283203125, 59.501953125, 10.3271484375, 59.4580078125))


 


    ' create a bitmap whoes size equals to the tile size.


    Using bitmap As New System.Drawing.Bitmap(256, 256)


      ' create a GeoCanvas which for drawing the passed layers.


      Dim geoCanvas As New GdiPlusGeoCanvas()


      geoCanvas.BeginDrawing(bitmap, cell.BoundingBox, mapUnit)


 


      SyncLock GebcoOneBathymetricLayer


        If Not GebcoOneBathymetricLayer.IsOpen Then


          GebcoOneBathymetricLayer.Open()


        End If


        Try


          GebcoOneBathymetricLayer.Draw(geoCanvas, New Collection(Of SimpleCandidate)())  '<<<--- Exception ocurs here


          Console.WriteLine("OK")


        Catch ex As Exception


          Console.WriteLine("Cell Col: " & cell.Column & " Row: " & cell.Row & " BB: " & cell.BoundingBox.ToString & vbCrLf & _


                            "Exception: " & ex.ToString())


        End Try


      End SyncLock


 


      geoCanvas.EndDrawing()


 


      ' create tile object to maintain current tile information.


      Dim tile As New BitmapTile(bitmap, cell.BoundingBox, ZoomLevelSet.GetZoomLevels(ZoomLevelIdx).Scale)


 


      ' save tile.


      tileCache.SaveTile(tile)


    End Using


 


    Console.ReadKey()


  End Sub


 


End Module


 

 



Hi Carlos, 
  
 Thanks for your post, this is because we set BaseShape.GeometryLibrary as GeometryLibrary.Unmanaged by default,  would you please add: 
  
 BaseShape.GeometryLibrary = GeometryLibrary.Managed; 
  
 This should solve the problem, because: 
  
 When using BaseShape.GeometryLibrary = GeometryLibrary.Managed, we use the NTS to check the data validation 
 When using BaseShape.GeometryLibrary = GeometryLibrary.Unmanaged or BaseShape.GeometryLibrary = GeometryLibrary.Defualt, we use the Sqltype  to check the data validation 
 As Sqltype have a stricker validation-checking, some data will not pass SqlType validation check and the exception will be thrown. 
  
 Hope it helps, 
  
 Johnny  


Hi Johnny, 
  
  I guessed it so, but in 6.0.260.0 it already was already unmanaged as default. In fact I have been using unmanaged since you introduced the sqltypes library long time ago (back in 5.5?).  So It should be other the reason…

Hi Carlos,
 
In this case, you should set it to Managed to pass the validation, the wkb is not recongnized as valid by Sql types but it’s valid by NTS. Here are the screencasts to show the differences.
 
Not Using it:
 
screencast.com/t/w5ZS95F1PozE
 
Using it
 
screencast.com/t/KlxXZYjPahFP
 
 
Regards,
Edgar

Hi Edgar, 
  
  I fully understand the difference between SQL Types and NTS, but the point here is that the same code specifying unmanaged (SQL Types) with 6.0.260.0 DLLs was working fine. 
  
  Do you attempt to MakeValid the invalid features internally or is there any other way to overcome this without give up the use of SQL types and return permanently to NTS library?

Carlos, 
  
 In version 6.0.260.0, we haven’t apply the Sql types validation to the BaseShape.CreateShapeFromWellKnownData, so there was no exception that time. We just added this validation recently so you got this exception. 
  
 Regards, 
 Edgar

Ok, that makes sense. Then, is there any way so BaseShape.CreateShapeFromWellKnownData tries call MakeValid before throwing the exception? 
  
  I guess you will discontinue NTS library at some point, so using it permanently doesn’t seem to be a good idea, or it is?

I think you can use the valid shape files or override the LineStyle.DrawCore method in this case, and implement like below,



Public Class MyLineStyle : Inherits LineStyle

    Sub New(geoPen As GeoPen)
        MyBase.New(geoPen)
    End Sub

    Protected Overrides Sub DrawCore(features As IEnumerable(Of Feature), canvas As GeoCanvas, labelsInThisLayer As Collection(Of SimpleCandidate), labelsInAllLayers As Collection(Of SimpleCandidate))

        Dim validFeature As New Collection(Of Feature)

        For Each feature As Feature In features
            validFeature.Add(feature.MakeValid())
        Next

        MyBase.DrawCore(validFeature, canvas, labelsInThisLayer, labelsInAllLayers)
    End Sub

End Class

and I'm not sure when will we give up the NTS, but I think providing the valid data is necessary is the main part.


Regards,


Edgar



Hi Edgar, 
  
  Providing valid data is fine when you own/control all the source shape files, this would be in a ideal world, unfortunately our is not, so the code should be protective instead of preventive. 
  
  Thanks for the LineStyle code sample, but how can I use it within your BaseShape.CreateShapeFromWellKnownData used in ThinkGeo.MapSuite.Core.Layer.Draw(GeoCanvas canvas, Collection`1 labelsInAllLayers)? I mean, I wish to continue using sql types library, to use the new dlls 6.0.345.0 or newer plus and use the not-under-my-control-shapefiles I have been using for a while now. Is it possible anyhow?

Carlos, 
  
 I think in this way you should inherit the ShapeFileFeatureLayer and override the methods which return features such as GetAllFeatures, GetFeaturesByIds, make them valid before returning. In this way the features are valid and they can pass the BaseShape.CreateShapeFromWellKnownData() internall and you will not worry about this method. 
  
 Regards, 
 Edgar