Skip to content

Commit

Permalink
add SpatialRef functions (#91)
Browse files Browse the repository at this point in the history
Co-authored-by: yohan.cabion <yohan.cabion.sii@externalgcp.ds.airbus.com>
  • Loading branch information
yohancabion and yohan.cabion committed May 18, 2022
1 parent 83746ad commit 45c86c1
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 6 deletions.
4 changes: 4 additions & 0 deletions errors.go
Expand Up @@ -128,6 +128,7 @@ func ErrLogger(fn ErrorHandler) interface {
SetSpatialRefOption
SieveFilterOption
SimplifyOption
SpatialRefValidateOption
TransformOption
UpdateFeatureOption
VSIHandlerOption
Expand Down Expand Up @@ -283,6 +284,9 @@ func (ec errorCallback) setSieveFilterOpt(sfo *sieveFilterOpts) {
func (ec errorCallback) setSimplifyOpt(o *simplifyOpts) {
o.errorHandler = ec.fn
}
func (ec errorCallback) setSpatialRefValidateOpt(o *spatialRefValidateOpts) {
o.errorHandler = ec.fn
}
func (ec errorCallback) setTransformOpt(o *trnOpts) {
o.errorHandler = ec.fn
}
Expand Down
9 changes: 9 additions & 0 deletions godal.cpp
Expand Up @@ -335,6 +335,15 @@ OGRSpatialReferenceH godalCreateUserSpatialRef(cctx *ctx, char *userInput) {
return sr;
}

void godalValidateSpatialRef(cctx *ctx, OGRSpatialReferenceH sr) {
godalWrap(ctx);
OGRErr gret = OSRValidate(sr);
if(gret!=0) {
forceOGRError(ctx,gret);
}
godalUnwrap();
}

OGRCoordinateTransformationH godalNewCoordinateTransformation(cctx *ctx, OGRSpatialReferenceH src, OGRSpatialReferenceH dst) {
godalWrap(ctx);
OGRCoordinateTransformationH tr = OCTNewCoordinateTransformation(src,dst);
Expand Down
34 changes: 34 additions & 0 deletions godal.go
Expand Up @@ -1982,12 +1982,24 @@ func (trn *Transform) TransformEx(x []float64, y []float64, z []float64, success
return nil
}

// EPSGTreatsAsLatLong returns TRUE if EPSG feels the SpatialRef should be treated as having lat/long coordinate ordering.
func (sr *SpatialRef) EPSGTreatsAsLatLong() bool {
ret := C.OSREPSGTreatsAsLatLong(sr.handle)
return ret != 0
}

// Geographic returns wether the SpatialRef is geographic
func (sr *SpatialRef) Geographic() bool {
ret := C.OSRIsGeographic(sr.handle)
return ret != 0
}

// Projected returns wether the SpatialRef is projected
func (sr *SpatialRef) Projected() bool {
ret := C.OSRIsProjected(sr.handle)
return ret != 0
}

// SemiMajor returns the SpatialRef's Semi Major Axis
func (sr *SpatialRef) SemiMajor() (float64, error) {
var err C.int
Expand All @@ -2008,6 +2020,17 @@ func (sr *SpatialRef) SemiMinor() (float64, error) {
return float64(sm), nil
}

// AttrValue Fetch indicated attribute of named node from within the WKT tree.
func (sr *SpatialRef) AttrValue(name string, child int) (string, bool) {
cstr := C.CString(name)
defer C.free(unsafe.Pointer(cstr))
cret := C.OSRGetAttrValue(sr.handle, cstr, C.int(child))
if cret != nil {
return C.GoString(cret), true
}
return "", false
}

// AuthorityName is used to query an AUTHORITY[] node from within the WKT tree, and fetch the authority name value.
//
// target is the partial or complete path to the node to get an authority from. i.e. "PROJCS", "GEOGCS", "GEOGCS|UNIT"
Expand Down Expand Up @@ -2052,6 +2075,17 @@ func (sr *SpatialRef) AutoIdentifyEPSG() error {
return nil
}

// Validate SRS tokens.
func (sr *SpatialRef) Validate(opts ...SpatialRefValidateOption) error {
vo := spatialRefValidateOpts{}
for _, opt := range opts {
opt.setSpatialRefValidateOpt(&vo)
}
cgc := createCGOContext(nil, vo.errorHandler)
C.godalValidateSpatialRef(cgc.cPointer(), sr.handle)
return cgc.close()
}

// Rasterize wraps GDALRasterize()
func (ds *Dataset) Rasterize(dstDS string, switches []string, opts ...RasterizeOption) (*Dataset, error) {
gopts := rasterizeOpts{}
Expand Down
1 change: 1 addition & 0 deletions godal.h
Expand Up @@ -63,6 +63,7 @@ extern "C" {
OGRSpatialReferenceH godalCreateWKTSpatialRef(cctx *ctx, char *wkt);
OGRSpatialReferenceH godalCreateProj4SpatialRef(cctx *ctx, char *proj);
OGRSpatialReferenceH godalCreateEPSGSpatialRef(cctx *ctx, int epsgCode);
void godalValidateSpatialRef(cctx *ctx, OGRSpatialReferenceH sr);
char* godalExportToWKT(cctx *ctx, OGRSpatialReferenceH sr);
OGRCoordinateTransformationH godalNewCoordinateTransformation(cctx *ctx, OGRSpatialReferenceH src, OGRSpatialReferenceH dst);
void godalDatasetSetSpatialRef(cctx *ctx, GDALDatasetH ds, OGRSpatialReferenceH sr);
Expand Down
23 changes: 17 additions & 6 deletions godal_test.go
Expand Up @@ -1536,6 +1536,7 @@ func TestNilSpatialRef(t *testing.T) {
assert.False(t, sr.IsSame(epsg4326))
assert.False(t, epsg4326.IsSame(sr))
assert.False(t, sr.Geographic())
assert.False(t, sr.Projected())
_, err := sr.SemiMajor()
assert.NoError(t, err)
_, err = sr.SemiMajor()
Expand All @@ -1554,12 +1555,9 @@ func TestProjMisc(t *testing.T) {
ds, _ := Open("testdata/test.tif")
sr := ds.SpatialRef()
epsg4326, _ := NewSpatialRefFromEPSG(4326)
if !epsg4326.IsSame(sr) {
t.Error("isSame failed")
}
if !epsg4326.Geographic() {
t.Error("not geographic")
}
assert.True(t, epsg4326.IsSame(sr), "isSame failed")
assert.True(t, epsg4326.Geographic(), "not geographic")
assert.True(t, epsg4326.EPSGTreatsAsLatLong())
sm, err := sr.SemiMajor()
assert.NoError(t, err)
assert.Equal(t, 6.378137e+06, sm)
Expand All @@ -1578,12 +1576,25 @@ func TestProjMisc(t *testing.T) {
assert.Equal(t, "9122", au)
au = sr.AuthorityCode("FOOBAR")
assert.Equal(t, "", au)
attr, ok := sr.AttrValue("GEOGCS", 0)
assert.True(t, ok)
assert.Equal(t, "WGS 84", attr)
attr, ok = sr.AttrValue("GEOGCS", 9999)
assert.False(t, ok)

err = sr.AutoIdentifyEPSG()
assert.NoError(t, err)

epsg32632, err := NewSpatialRefFromEPSG(32632)
assert.NoError(t, err)
assert.NoError(t, sr.Validate())
assert.True(t, epsg32632.Projected())
assert.False(t, epsg32632.EPSGTreatsAsLatLong())

l, err := NewSpatialRefFromWKT(`LOCAL_CS[,UNIT["m",1]]`)
assert.NoError(t, err)
ehc := eh()
assert.Error(t, l.Validate(ErrLogger(ehc.ErrorHandler)))
err = l.AutoIdentifyEPSG()
assert.Error(t, err)
_, err = l.SemiMajor()
Expand Down
12 changes: 12 additions & 0 deletions options.go
Expand Up @@ -1083,6 +1083,18 @@ func Values(vals ...float64) interface {
return floatValues{vals}
}

type spatialRefValidateOpts struct {
errorHandler ErrorHandler
}

// SpatialRefValidateOption is an option that can be passed to SpatialRef.Validate()
//
// Available SpatialRefValidateOptions are:
// - ErrLogger
type SpatialRefValidateOption interface {
setSpatialRefValidateOpt(o *spatialRefValidateOpts)
}

type rasterizeOpts struct {
create []string
config []string
Expand Down

0 comments on commit 45c86c1

Please sign in to comment.