Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge upstream gdal #3

Merged
merged 59 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
b995140
Update gdal.go
bayuemu Sep 20, 2019
56cda83
Merge pull request #44 from bayuemu/patch-1
martende Sep 21, 2019
0443cbf
Add new wrap api: Distance3D
victor9011 Oct 9, 2019
21e812e
Add new wrap api: Distance3D
victor9011 Oct 9, 2019
8bafe47
Merge pull request #45 from VictorZhucx/master
martende Oct 9, 2019
ce646db
Support getting a MetadataItem from a RasterBand
bnoon Oct 17, 2019
517c018
Merge pull request #46 from bnoon/master
martende Oct 18, 2019
7794bc5
Fix gdal import path
anees-a Feb 28, 2020
0a44fe2
Prevent panic on missing metadata
pboyd Mar 25, 2020
5374c63
Merge pull request #47 from aneeskA/docfix
byteplane May 31, 2020
ccd159b
Merge pull request #48 from pboyd/master
byteplane May 31, 2020
6ca8e0e
Added Go modules awareness
mtfelian Jun 2, 2020
ffcc4a9
implementing GDALGridCreate wrapper
mtfelian Jun 2, 2020
93e6d21
implementing GDALGridCreate wrapper...
mtfelian Jun 2, 2020
9cdf945
implementing GDALGridCreate wrapper...
mtfelian Jun 2, 2020
003e1ac
implementing and debugging GDALGridCreate wrapper...
mtfelian Jun 2, 2020
d0c97b2
implementing and debugging GDALGridCreate wrapper... trying with line…
mtfelian Jun 2, 2020
ec9fdf3
implemented GDALGridCreate wrapper... added test
mtfelian Jun 3, 2020
11f890c
changed imports
mtfelian Jun 3, 2020
c27d5fd
improved gridding example
mtfelian Jun 3, 2020
4c5dda2
Merge pull request #51 from mtfelian/master
martende Jun 3, 2020
da1577f
changed imports
mtfelian Jun 3, 2020
3a92ff2
changed imports
mtfelian Jun 3, 2020
2f06838
changed imports
mtfelian Jun 3, 2020
c921973
changed cgo directives
mtfelian Jun 4, 2020
cf6a59f
fallback to pkg-config
mtfelian Jun 4, 2020
092f31c
removed methods that are no longer supported in 3.x versions of GDAL
Aug 5, 2020
6f20053
Update gdal.go
bayuemu Jan 15, 2021
635e469
Merge pull request #63 from bayuemu/patch-2
martende Jan 15, 2021
6bc8248
Merge pull request #54 from tingold/master
martende Jan 30, 2021
b34c40b
removed methods which were removed from GDAL 3
mtfelian Feb 19, 2021
fbe47ea
changed module name
mtfelian Feb 19, 2021
c9883f7
removed code duplication
mtfelian Mar 4, 2021
bf52640
added DEMProcessing utility func
mtfelian Mar 4, 2021
95ad704
DEMProcessing: bugfix
mtfelian Mar 4, 2021
fb0b57d
changed imports on branch for PR
mtfelian Mar 4, 2021
28463f9
Merge branch 'master' into lukerothgdal
mtfelian Mar 4, 2021
100c8de
changed Warp header
mtfelian Mar 10, 2021
ec016ea
changed example
mtfelian Mar 10, 2021
b060f6d
Merge branch 'master' into lukerothgdal
mtfelian Mar 10, 2021
36d7a1b
Merge remote-tracking branch 'origin/lukerothgdal' into lukerothgdal
mtfelian Mar 10, 2021
b66f07d
Merge pull request #64 from mtfelian/lukerothgdal
byteplane Mar 10, 2021
bcc97c0
Fixed gdal v3 incompatible method args type
Apr 18, 2021
92c99e3
Update utilities.go
bayuemu Apr 20, 2021
3694426
Update utilities.go
bayuemu Apr 21, 2021
4b7812b
Merge pull request #67 from bayuemu/patch-3
martende Apr 29, 2021
0ed96ec
Merge pull request #66 from sergevoloshyn/master
martende Apr 29, 2021
b9b757c
Prevent panic on the last entry of metadata
May 12, 2021
d2a18da
Splits out darwin cgo config adding -Wl,-undefined,dynamic_lookup to …
May 6, 2021
62421ae
Update utilities.go
bayuemu May 27, 2021
3095123
Add SetAxisMappingStrategy
julienr Oct 31, 2021
c3802da
Merge pull request #73 from bayuemu/patch-4
martende Nov 1, 2021
2227430
Merge pull request #74 from julienr/master
martende Nov 1, 2021
e1a4fe7
Merge pull request #70 from osklyar/metadata-fix
martende Nov 1, 2021
b208ffe
Merge pull request #72 from osklyar/darwin-fix
martende Nov 1, 2021
eae6402
support mac arm64 arch
ningfc Nov 8, 2021
b571df3
Merge pull request #76 from ningfc/master
byteplane Nov 9, 2021
be84fd8
merge from upstream
May 10, 2022
ae02249
updated versions in README
May 10, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
examples/tiff/tiff
examples/translate/translate
examples/warp/warp
examples/grid/grid
.idea
2 changes: 1 addition & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Installation
Compatibility
-------------

This software has been tested most recently on Ubuntu 18.10, GDAL version 2.3.2.
This software has been tested most recently on Debian 11 Bullseye, GDAL version 3.2.2.

-------------
Examples
Expand Down
245 changes: 239 additions & 6 deletions algorithms.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@ package gdal
/*
#include "go_gdal.h"
#include "gdal_version.h"

#cgo linux pkg-config: gdal
#cgo darwin pkg-config: gdal
#cgo windows LDFLAGS: -Lc:/gdal/release-1600-x64/lib -lgdal_i
#cgo windows CFLAGS: -IC:/gdal/release-1600-x64/include
*/
import "C"
import (
"errors"
"fmt"
"unsafe"
)
Expand Down Expand Up @@ -302,5 +298,242 @@ func (src RasterBand) SieveFilter(
/* Gridding functions */
/* --------------------------------------------- */

//Unimplemented: CreateGrid
// GridAlgorithm represents Grid Algorithm code
type GridAlgorithm int

//
const (
GA_InverseDistancetoAPower = GridAlgorithm(C.GGA_InverseDistanceToAPower)
GA_MovingAverage = GridAlgorithm(C.GGA_MovingAverage)
GA_NearestNeighbor = GridAlgorithm(C.GGA_NearestNeighbor)
GA_MetricMinimum = GridAlgorithm(C.GGA_MetricMinimum)
GA_MetricMaximum = GridAlgorithm(C.GGA_MetricMaximum)
GA_MetricRange = GridAlgorithm(C.GGA_MetricRange)
GA_MetricCount = GridAlgorithm(C.GGA_MetricCount)
GA_MetricAverageDistance = GridAlgorithm(C.GGA_MetricAverageDistance)
GA_MetricAverageDistancePts = GridAlgorithm(C.GGA_MetricAverageDistancePts)
GA_Linear = GridAlgorithm(C.GGA_Linear)
GA_InverseDistanceToAPowerNearestNeighbor = GridAlgorithm(C.GGA_InverseDistanceToAPowerNearestNeighbor)
)

// GridLinearOptions: Linear method control options.
type GridLinearOptions struct {
// Radius: in case the point to be interpolated does not fit into a triangle of the Delaunay triangulation,
// use that maximum distance to search a nearest neighbour, or use nodata otherwise. If set to -1, the search
// distance is infinite. If set to 0, nodata value will be always used.
Radius float64
// NoDataValue: no data marker to fill empty points.
NoDataValue float64
}

// GridInverseDistanceToAPowerOptions: Inverse distance to a power method control options.
type GridInverseDistanceToAPowerOptions struct {
// Power: Weighting power
Power float64
// Smoothing: Smoothing parameter
Smoothing float64
// AnisotropyRatio: Reserved for future use
AnisotropyRatio float64
// AnisotropyAngle: Reserved for future use
AnisotropyAngle float64
// Radius1: The first radius (X axis if rotation angle is 0) of search ellipse.
Radius1 float64
// Radius2: The second radius (Y axis if rotation angle is 0) of search ellipse.
Radius2 float64
// Angle: Angle of ellipse rotation in degrees. Ellipse rotated counter clockwise.
Angle float64
// MaxPoints: Maximum number of data points to use.
// Do not search for more points than this number. If less amount of points found the grid node
// considered empty and will be filled with NODATA marker.
MaxPoints uint32
// MinPoints: Minimum number of data points to use.
// If less amount of points found the grid node considered empty and will be filled with NODATA marker.
MinPoints uint32
// NoDataValue: No data marker to fill empty points.
NoDataValue float64
}

// GridInverseDistanceToAPowerNearestNeighborOptions: Inverse distance to a power, with nearest neighbour search,
// control options
type GridInverseDistanceToAPowerNearestNeighborOptions struct {
// Power: Weighting power
Power float64
// Radius: The radius of search circle
Radius float64
// Smoothing: Smoothing parameter
Smoothing float64
// MaxPoints: Maximum number of data points to use.
// Do not search for more points than this number. If less amount of points found the grid node
// considered empty and will be filled with NODATA marker.
MaxPoints uint32
// MinPoints: Minimum number of data points to use.
// If less amount of points found the grid node considered empty and will be filled with NODATA marker.
MinPoints uint32
// NoDataValue: No data marker to fill empty points.
NoDataValue float64
}

// GridMovingAverageOptions: Moving average method control options
type GridMovingAverageOptions struct {
// Radius1: The first radius (X axis if rotation angle is 0) of search ellipse.
Radius1 float64
// Radius2: The second radius (Y axis if rotation angle is 0) of search ellipse.
Radius2 float64
// Angle: Angle of ellipse rotation in degrees. Ellipse rotated counter clockwise.
Angle float64
// MinPoints: Minimum number of data points to use.
// If less amount of points found the grid node considered empty and will be filled with NODATA marker.
MinPoints uint32
// NoDataValue: No data marker to fill empty points.
NoDataValue float64
}

// GridNearestNeighborOptions: Nearest neighbor method control options.
type GridNearestNeighborOptions struct {
// Radius1: The first radius (X axis if rotation angle is 0) of search ellipse.
Radius1 float64
// Radius2: The second radius (Y axis if rotation angle is 0) of search ellipse.
Radius2 float64
// Angle: Angle of ellipse rotation in degrees. Ellipse rotated counter clockwise.
Angle float64
// NoDataValue: No data marker to fill empty points.
NoDataValue float64
}

// GridDataMetricsOptions: Data metrics method control options
type GridDataMetricsOptions struct {
// Radius1: The first radius (X axis if rotation angle is 0) of search ellipse.
Radius1 float64
// Radius2: The second radius (Y axis if rotation angle is 0) of search ellipse.
Radius2 float64
// Angle: Angle of ellipse rotation in degrees. Ellipse rotated counter clockwise.
Angle float64
// MinPoints: Minimum number of data points to use.
// If less amount of points found the grid node considered empty and will be filled with NODATA marker.
MinPoints uint32
// NoDataValue: No data marker to fill empty points.
NoDataValue float64
}

var errInvalidOptionsTypeWasPassed = errors.New("invalid options type was passed")

// GridCreate: Create regular grid from the scattered data.
// This function takes the arrays of X and Y coordinates and corresponding Z values as input and computes
// regular grid (or call it a raster) from these scattered data. You should supply geometry and extent of the
// output grid.
func GridCreate(
algorithm GridAlgorithm,
options interface{},
x, y, z []float64,
xMin, xMax, yMin, yMax float64,
nX, nY uint,
progress ProgressFunc,
data interface{},
) ([]float64, error) {
if len(x) != len(y) || len(x) != len(z) {
return nil, errors.New("lengths of x, y, z should equal")
}

poptions := unsafe.Pointer(nil)
switch algorithm {
case GA_InverseDistancetoAPower:
soptions, ok := options.(GridInverseDistanceToAPowerOptions)
if !ok {
return nil, errInvalidOptionsTypeWasPassed
}
poptions = unsafe.Pointer(&C.GDALGridInverseDistanceToAPowerOptions{
dfPower: C.double(soptions.Power),
dfSmoothing: C.double(soptions.Smoothing),
dfAnisotropyRatio: C.double(soptions.AnisotropyRatio),
dfAnisotropyAngle: C.double(soptions.AnisotropyAngle),
dfRadius1: C.double(soptions.Radius1),
dfRadius2: C.double(soptions.Radius2),
dfAngle: C.double(soptions.Angle),
nMaxPoints: C.uint(soptions.MaxPoints),
nMinPoints: C.uint(soptions.MinPoints),
dfNoDataValue: C.double(soptions.NoDataValue),
})
case GA_InverseDistanceToAPowerNearestNeighbor:
soptions, ok := options.(GridInverseDistanceToAPowerNearestNeighborOptions)
if !ok {
return nil, errInvalidOptionsTypeWasPassed
}
poptions = unsafe.Pointer(&C.GDALGridInverseDistanceToAPowerNearestNeighborOptions{
dfPower: C.double(soptions.Power),
dfRadius: C.double(soptions.Radius),
dfSmoothing: C.double(soptions.Smoothing),
nMaxPoints: C.uint(soptions.MaxPoints),
nMinPoints: C.uint(soptions.MinPoints),
dfNoDataValue: C.double(soptions.NoDataValue),
})
case GA_MovingAverage:
soptions, ok := options.(GridMovingAverageOptions)
if !ok {
return nil, errInvalidOptionsTypeWasPassed
}
poptions = unsafe.Pointer(&C.GDALGridMovingAverageOptions{
dfRadius1: C.double(soptions.Radius1),
dfRadius2: C.double(soptions.Radius2),
dfAngle: C.double(soptions.Angle),
nMinPoints: C.uint(soptions.MinPoints),
dfNoDataValue: C.double(soptions.NoDataValue),
})
case GA_NearestNeighbor:
soptions, ok := options.(GridNearestNeighborOptions)
if !ok {
return nil, errInvalidOptionsTypeWasPassed
}
poptions = unsafe.Pointer(&C.GDALGridNearestNeighborOptions{
dfRadius1: C.double(soptions.Radius1),
dfRadius2: C.double(soptions.Radius2),
dfAngle: C.double(soptions.Angle),
dfNoDataValue: C.double(soptions.NoDataValue),
})
case GA_MetricMinimum, GA_MetricMaximum, GA_MetricCount, GA_MetricRange,
GA_MetricAverageDistance, GA_MetricAverageDistancePts:
soptions, ok := options.(GridDataMetricsOptions)
if !ok {
return nil, errInvalidOptionsTypeWasPassed
}
poptions = unsafe.Pointer(&C.GDALGridDataMetricsOptions{
dfRadius1: C.double(soptions.Radius1),
dfRadius2: C.double(soptions.Radius2),
dfAngle: C.double(soptions.Angle),
nMinPoints: C.uint(soptions.MinPoints),
dfNoDataValue: C.double(soptions.NoDataValue),
})
case GA_Linear:
soptions, ok := options.(GridLinearOptions)
if !ok {
return nil, errInvalidOptionsTypeWasPassed
}
poptions = unsafe.Pointer(&C.GDALGridLinearOptions{
dfRadius: C.double(soptions.Radius),
dfNoDataValue: C.double(soptions.NoDataValue),
})
}

buffer := make([]float64, nX*nY)
arg := &goGDALProgressFuncProxyArgs{progress, data}
err := C.GDALGridCreate(
C.GDALGridAlgorithm(algorithm),
poptions,
C.uint(uint(len(x))),
(*C.double)(unsafe.Pointer(&x[0])),
(*C.double)(unsafe.Pointer(&y[0])),
(*C.double)(unsafe.Pointer(&z[0])),
C.double(xMin),
C.double(xMax),
C.double(yMin),
C.double(yMax),
C.uint(nX),
C.uint(nY),
C.GDALDataType(Float64),
unsafe.Pointer(&buffer[0]),
C.goGDALProgressFuncProxyB(),
unsafe.Pointer(arg),
).Err()
return buffer, err
}

//Unimplemented: ComputeMatchingPoints
80 changes: 80 additions & 0 deletions algorithms_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package gdal

import (
"errors"
"fmt"
"io/ioutil"
"math"
"strconv"
"strings"
"testing"
)

func readGridFile(filename string) (x, y, z []float64, err error) {
var b []byte
if b, err = ioutil.ReadFile(filename); err != nil {
return
}
arr := strings.Split(string(b), "\n")
x, y, z = make([]float64, len(arr)), make([]float64, len(arr)), make([]float64, len(arr))
for i, el := range arr {
xyz := strings.Split(el, ",")
if len(xyz) != 3 {
err = errors.New("wrong input file format, should be CSV with 3 columns: y,x,z")
}

if y[i], err = strconv.ParseFloat(xyz[0], 64); err != nil {
return
}
if x[i], err = strconv.ParseFloat(xyz[1], 64); err != nil {
return
}
if z[i], err = strconv.ParseFloat(xyz[2], 64); err != nil {
return
}
}
return
}

func TestGridCreate(t *testing.T) {
x, y, z, err := readGridFile("testdata/grid.csv")
if err != nil {
t.Fatalf("failed to readGridFile: %v", err)
return
}
var nX, nY uint = 420, 470

// finding max and min values
var xMin, xMax, yMin, yMax = math.MaxFloat64, -math.MaxFloat64, math.MaxFloat64, -math.MaxFloat64
for i := range x {
if x[i] < xMin {
xMin = x[i]
}
if x[i] > xMax {
xMax = x[i]
}
if y[i] < yMin {
yMin = y[i]
}
if y[i] > yMax {
yMax = y[i]
}
}

fmt.Println("Calling gdal.GridCreate")
data, err := GridCreate(
GA_Linear,
GridLinearOptions{Radius: -1, NoDataValue: 0},
x, y, z,
xMin, xMax, yMin, yMax,
nX, nY,
DummyProgress,
nil,
)
if err != nil {
t.Errorf("GridCreate: %v", err)
}
if expectedDataLen := int(nX * nY); len(data) != expectedDataLen {
t.Errorf("expected length of data equal to %d", expectedDataLen)
}
}
Loading