ThinkGeo.com    |     Documentation    |     Premium Support

Line Buffering Question

Hi.


I would like to know how buffering is applied to the line shape.


The bounding box height of the buffer result is more (270 feet) than expected (200 feet)


 



      'Create horizontal line 100 feet long
      Dim p1 As New PointShape(-95.606609822483733, 41.805456965812482)
      Dim p2 As New PointShape(-95.606609822483733, 41.805456965812482)
      p2.TranslateByOffset(100, 0, GeographyUnit.DecimalDegree, DistanceUnit.Feet)

      Dim ls As New LineShape
      ls.Vertices.Add(New Vertex(p1))
      ls.Vertices.Add(New Vertex(p2))

      'Check the length of the line = 100.974975459508 - Approximately correct
      Console.WriteLine("Length: " & ls.GetLength(GeographyUnit.DecimalDegree, DistanceUnit.Feet))

      'Apply 100 feet buffer to the line
      Dim mps As MultipolygonShape = ls.Buffer(100, GeographyUnit.DecimalDegree, DistanceUnit.Feet)

      'Get bounding box from the buffer result
      Dim ext As RectangleShape = mps.GetBoundingBox

      'Check the width of the bounding box = 302.92317075103 - Approximately correct
      ls = New LineShape
      ls.Vertices.Add(New Vertex(ext.UpperLeftPoint))
      ls.Vertices.Add(New Vertex(ext.UpperRightPoint))

      Console.WriteLine("Width: " & ls.GetLength(GeographyUnit.DecimalDegree, DistanceUnit.Feet))

      'Check the height of the bounding box = 270.923746270921 - Expected +- 200 feet
      'Where extra 70.92 feet come from?
      ls = New LineShape
      ls.Vertices.Add(New Vertex(ext.UpperLeftPoint))
      ls.Vertices.Add(New Vertex(ext.LowerLeftPoint))

      Console.WriteLine("Height: " & ls.GetLength(GeographyUnit.DecimalDegree, DistanceUnit.Feet))


 Hi Sergei, 


Thanks for your post, the reason for this phenomenon is that both NTS and SqlTypes will buffer by decimal degree, our core will change the 100 feet distance to decimal degree by using


DecimalDegreeHelper. GetLongitudeDifferenceFromDistance(double distance, DistanceUnit distanceUnit, double latitude). And when latitude is 41.805456965812482, 100 feet longitude line covers more degrees than when latitude is 0, so the distance buffered latitude is larger than ecpected. 


If you change 


   Dim p1 As New PointShape(-95.606609822483733, 41.805456965812482)


   Dim p2 As New PointShape(-95.606609822483733, 41.805456965812482)


To 


   Dim p1 As New PointShape(-95.606609822483733, 0)
   Dim p2 As New PointShape(-95.606609822483733, 0)

You will find out that the height will be about  200.


 


Hope it helps 


Johnny



Johnny,


thank you for response.


Calculating the height has nothing to do with the Y value.


Y can be any decimal degree value and when buffer is applied, height should be the same regardless of Y.


Here is the same example again but this time I'm using Micrsofoft Sql Server STBuffer function and height is correct now.


This is the new output:


 


Length: 100.974975459508


Width: 300.454959392744


Height: 200.228274310505



Imports ThinkGeo
Imports ThinkGeo.MapSuite
Imports ThinkGeo.MapSuite.Core
Imports ThinkGeo.MapSuite.DesktopEdition

Imports Microsoft.SqlServer.Types
Imports System.Data.SqlTypes

  Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Try
      'Create horizontal line 100 feet long
      Dim p1 As New PointShape(-95.606609822483733, 41.805456965812482)
      Dim p2 As New PointShape(-95.606609822483733, 41.805456965812482)
      p2.TranslateByOffset(100, 0, GeographyUnit.DecimalDegree, DistanceUnit.Feet)

      Dim ls As New LineShape
      ls.Vertices.Add(New Vertex(p1))
      ls.Vertices.Add(New Vertex(p2))

      'Check the length of the line = 100.974975459508 - Approximately correct
      Console.WriteLine("Length: " & ls.GetLength(GeographyUnit.DecimalDegree, DistanceUnit.Feet))

      'Apply 100 feet buffer to the line
      'Dim mps As MultipolygonShape = ls.Buffer(100, GeographyUnit.DecimalDegree, DistanceUnit.Feet)
      Dim ps As PolygonShape = Buffer(100, ls)

      'Get bounding box from the buffer result
      'Dim ext As RectangleShape = mps.GetBoundingBox
      Dim ext As RectangleShape = ps.GetBoundingBox

      'Check the width of the bounding box = 302.92317075103 - Approximately correct
      ls = New LineShape
      ls.Vertices.Add(New Vertex(ext.UpperLeftPoint))
      ls.Vertices.Add(New Vertex(ext.UpperRightPoint))

      Console.WriteLine("Width: " & ls.GetLength(GeographyUnit.DecimalDegree, DistanceUnit.Feet))

      'Check the height of the bounding box = 270.923746270921 - Expected +- 200 feet
      'Where extra 70.92 feet come from?
      ls = New LineShape
      ls.Vertices.Add(New Vertex(ext.UpperLeftPoint))
      ls.Vertices.Add(New Vertex(ext.LowerLeftPoint))

      Console.WriteLine("Height: " & ls.GetLength(GeographyUnit.DecimalDegree, DistanceUnit.Feet))
  End Sub

  Private Function Buffer(feet As Double, ls As ThinkGeo.MapSuite.Core.LineShape) As ThinkGeo.MapSuite.Core.PolygonShape
    Dim wkt As String = ls.GetWellKnownText

    Dim srid As Integer = 4326
    Dim sc As New System.Data.SqlTypes.SqlChars(wkt)
    Dim geom As Microsoft.SqlServer.Types.SqlGeometry = Microsoft.SqlServer.Types.SqlGeometry.STGeomFromText(sc, srid)

    If Not geom.STIsValid Then
      geom = geom.MakeValid
      geom = geom.STUnion(geom.STStartPoint)

      sc = New System.Data.SqlTypes.SqlChars(geom.ToString)
    End If

    Dim geog As Microsoft.SqlServer.Types.SqlGeography = Microsoft.SqlServer.Types.SqlGeography.STGeomFromWKB(geom.STAsBinary, srid)

    'convert feet to meters
    wkt = geog.STBuffer(feet / 3.2808).ToString

    Dim bs As ThinkGeo.MapSuite.Core.BaseShape = ThinkGeo.MapSuite.Core.BaseShape.CreateShapeFromWellKnownData(wkt)

    Return CType(bs, ThinkGeo.MapSuite.Core.PolygonShape)
        
  End Function
  Here is buffer applied to the 100x100 feet rectangle:




Hi Sergei, 
  
 Thanks for your further information, and I noticed that you are using SqlGeography.STBuffer, but inside our core we are using SqlGeometry.STBuffer, the same result with ours will be found by using the following code: 
 geom.STBuffer(DecimalDegreesHelper.GetLongitudeDifferenceFromDistance(100, DistanceUnit.Feet, 41.805456965812482)).ToString()); 
 Instead of  
 geog.STBuffer(feet / 3.2808).ToString(); 
  
 If you have any question, please feel free to let us know. 
  
 Hope it helps. 
  
 Edgar