Skip to content

Commit

Permalink
add misc Layer functions, fix Layer.NewFeature (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
yohancabion committed May 19, 2022
1 parent 0a12694 commit 548d787
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 12 deletions.
9 changes: 5 additions & 4 deletions errors.go
Expand Up @@ -85,13 +85,14 @@ func ErrLogger(fn ErrorHandler) interface {
errorAndLoggingOption
BandCreateMaskOption
BandIOOption
//BoundsOption
BoundsOption
BufferOption
BuildOverviewsOption
BuildVRTOption
ClearOverviewsOption
CloseOption
CopyLayerOption
CreateFeatureOption
CreateLayerOption
CreateSpatialRefOption
DatasetCreateMaskOption
Expand Down Expand Up @@ -152,12 +153,9 @@ func (ec errorCallback) setBandCreateMaskOpt(o *bandCreateMaskOpts) {
func (ec errorCallback) setBandIOOpt(o *bandIOOpts) {
o.errorHandler = ec.fn
}

/*
func (ec errorCallback) setBoundsOpt(o *boundsOpts) {
o.errorHandler = ec.fn
}
*/
func (ec errorCallback) setBufferOpt(o *bufferOpts) {
o.errorHandler = ec.fn
}
Expand All @@ -179,6 +177,9 @@ func (ec errorCallback) setCloseOpt(o *closeOpts) {
func (ec errorCallback) setCopyLayerOpt(o *copyLayerOpts) {
o.errorHandler = ec.fn
}
func (ec errorCallback) setCreateFeatureOpt(cfo *createFeatureOpts) {
cfo.errorHandler = ec.fn
}
func (ec errorCallback) setCreateLayerOpt(o *createLayerOpts) {
o.errorHandler = ec.fn
}
Expand Down
24 changes: 22 additions & 2 deletions godal.cpp
Expand Up @@ -788,6 +788,17 @@ OGRLayerH godalCopyLayer(cctx *ctx, GDALDatasetH ds, OGRLayerH layer, char *name
return ret;
}

void godalLayerGetExtent(cctx *ctx, OGRLayerH layer, OGREnvelope *envelope) {
godalWrap(ctx);
OGRErr gret = OGR_L_GetExtent(layer, envelope, 1);
if (gret != OGRERR_NONE) {
forceOGRError(ctx,gret);
} else if(envelope==nullptr) {
forceError(ctx);
}
godalUnwrap();
}

void godalLayerFeatureCount(cctx *ctx, OGRLayerH layer, int *count) {
godalWrap(ctx);
GIntBig gcount = OGR_L_GetFeatureCount(layer, 1);
Expand Down Expand Up @@ -1063,6 +1074,15 @@ void godalGeometryTransform(cctx *ctx, OGRGeometryH geom, OGRCoordinateTransform
godalUnwrap();
}

void godalLayerCreateFeature(cctx *ctx, OGRLayerH layer, OGRFeatureH feat) {
godalWrap(ctx);
OGRErr oe = OGR_L_CreateFeature(layer,feat);
if(oe != OGRERR_NONE) {
forceOGRError(ctx,oe);
}
godalUnwrap();
}

OGRFeatureH godalLayerNewFeature(cctx *ctx, OGRLayerH layer, OGRGeometryH geom) {
godalWrap(ctx);
OGRFeatureH hFeature = OGR_F_Create( OGR_L_GetLayerDefn( layer ) );
Expand All @@ -1074,8 +1094,8 @@ OGRFeatureH godalLayerNewFeature(cctx *ctx, OGRLayerH layer, OGRGeometryH geom)
OGRErr oe=OGRERR_NONE;
if (hFeature!=nullptr && geom!=nullptr) {
oe = OGR_F_SetGeometry(hFeature,geom);
if (oe != OGRERR_NONE) {
oe = OGR_L_SetFeature(layer,hFeature);
if (oe == OGRERR_NONE) {
oe = OGR_L_CreateFeature(layer,hFeature);
}
}
if(oe != OGRERR_NONE) {
Expand Down
54 changes: 54 additions & 0 deletions godal.go
Expand Up @@ -2286,6 +2286,46 @@ func (layer Layer) handle() C.OGRLayerH {
return C.OGRLayerH(layer.majorObject.cHandle)
}

// Name returns the layer name
func (layer Layer) Name() string {
return C.GoString(C.OGR_L_GetName(layer.handle()))
}

// Type returns the layer geometry type.
func (layer Layer) Type() GeometryType {
return GeometryType(C.OGR_L_GetGeomType(layer.handle()))
}

//Bounds returns the layer's envelope in the order minx,miny,maxx,maxy
func (layer Layer) Bounds(opts ...BoundsOption) ([4]float64, error) {
bo := boundsOpts{}
for _, o := range opts {
o.setBoundsOpt(&bo)
}
var env C.OGREnvelope
cgc := createCGOContext(nil, bo.errorHandler)
C.godalLayerGetExtent(cgc.cPointer(), layer.handle(), &env)
if err := cgc.close(); err != nil {
return [4]float64{}, err
}
bnds := [4]float64{
float64(env.MinX),
float64(env.MinY),
float64(env.MaxX),
float64(env.MaxY),
}
if bo.sr == nil {
return bnds, nil
}
sr := layer.SpatialRef()
defer sr.Close()
bnds, err := reprojectBounds(bnds, sr, bo.sr)
if err != nil {
return [4]float64{}, err
}
return bnds, nil
}

// FeatureCount returns the number of features in the layer
func (layer Layer) FeatureCount(opts ...FeatureCountOption) (int, error) {
fco := &featureCountOpts{}
Expand Down Expand Up @@ -2590,6 +2630,20 @@ func (layer Layer) NextFeature() *Feature {
return &Feature{hndl}
}

// CreateFeature copy a feature on Layer
func (layer Layer) CreateFeature(feat *Feature, opts ...CreateFeatureOption) error {
cfo := createFeatureOpts{}
for _, opt := range opts {
opt.setCreateFeatureOpt(&cfo)
}
cgc := createCGOContext(nil, cfo.errorHandler)
C.godalLayerCreateFeature(cgc.cPointer(), layer.handle(), feat.handle)
if err := cgc.close(); err != nil {
return err
}
return nil
}

// NewFeature creates a feature on Layer
func (layer Layer) NewFeature(geom *Geometry, opts ...NewFeatureOption) (*Feature, error) {
nfo := newFeatureOpts{}
Expand Down
2 changes: 2 additions & 0 deletions godal.h
Expand Up @@ -92,8 +92,10 @@ extern "C" {
void godalFillNoData(cctx *ctx, GDALRasterBandH in, GDALRasterBandH mask, int maxDistance, int iterations, char **opts);
void godalSieveFilter(cctx *ctx, GDALRasterBandH bnd, GDALRasterBandH mask, GDALRasterBandH dst, int sizeThreshold, int connectedNess);

void godalLayerGetExtent(cctx *ctx, OGRLayerH layer, OGREnvelope *envelope);
void godalLayerFeatureCount(cctx *ctx, OGRLayerH layer, int *count);
void godalLayerSetFeature(cctx *ctx, OGRLayerH layer, OGRFeatureH feat);
void godalLayerCreateFeature(cctx *ctx, OGRLayerH layer, OGRFeatureH feat);
OGRFeatureH godalLayerNewFeature(cctx *ctx, OGRLayerH layer, OGRGeometryH geom);
void godalLayerDeleteFeature(cctx *ctx, OGRLayerH layer, OGRFeatureH feat);
void godalFeatureSetGeometry(cctx *ctx, OGRFeatureH feat, OGRGeometryH geom);
Expand Down
28 changes: 25 additions & 3 deletions godal_test.go
Expand Up @@ -2447,12 +2447,34 @@ func TestVectorLayer(t *testing.T) {
assert.Error(t, ds.Write(0, 0, buf, 3, 3))
assert.Error(t, ds.Write(0, 0, buf, 3, 3, ErrLogger(ehc.ErrorHandler)))

sr3857, _ := NewSpatialRefFromEPSG(3857)
defer sr3857.Close()

layer := ds.Layers()[0]
assert.Equal(t, layer.Name(), "test")
assert.Equal(t, layer.Type(), GTPolygon)
bounds, err := layer.Bounds()
assert.NoError(t, err)
assert.Equal(t, bounds, [4]float64{100, 0, 101, 1})
_, err = layer.Bounds(sr3857)
assert.NoError(t, err)
_, err = layer.Bounds(&SpatialRef{})
assert.Error(t, err)
_, err = Layer{}.Bounds(ErrLogger(ehc.ErrorHandler))
assert.Error(t, err)

assert.Nil(t, ds.LayerByName("none"))
testLayer := ds.LayerByName("test")
assert.NotNil(t, testLayer)
vds, _ := CreateVector(Memory, "")
_, err = vds.CopyLayer(*testLayer, "copied")
copiedLayer, err := vds.CopyLayer(*testLayer, "copied")
assert.NoError(t, err)
testLayer.ResetReading()
feature := testLayer.NextFeature()
err = copiedLayer.CreateFeature(feature)
assert.NoError(t, err)
err = copiedLayer.CreateFeature(&Feature{}, ErrLogger(ehc.ErrorHandler))
assert.Error(t, err)
_, err = vds.CopyLayer(Layer{}, "empty", ErrLogger(ehc.ErrorHandler))
assert.Error(t, err)
_ = vds.Close()
Expand Down Expand Up @@ -2481,8 +2503,6 @@ func TestVectorLayer(t *testing.T) {

sr4326, _ := NewSpatialRefFromEPSG(4326)
defer sr4326.Close()
sr3857, _ := NewSpatialRefFromEPSG(3857)
defer sr3857.Close()
l2, err := dds.CreateLayer("t2", sr4326, GTPoint)
assert.NoError(t, err)
assert.True(t, sr4326.IsSame(l2.SpatialRef()))
Expand Down Expand Up @@ -2793,6 +2813,8 @@ func TestFeatureAttributes(t *testing.T) {
pnt, _ := NewGeometryFromWKT("POINT (1 1)", nil)
nf, err := lyr.NewFeature(pnt)
assert.NoError(t, err)
fc, _ := lyr.FeatureCount()
assert.Equal(t, fc, 1)
attrs := nf.Fields()
sfield := attrs["strCol"]
assert.Equal(t, FTString, sfield.Type())
Expand Down
12 changes: 12 additions & 0 deletions options.go
Expand Up @@ -1156,6 +1156,18 @@ type DatasetVectorTranslateOption interface {
setDatasetVectorTranslateOpt(dwo *dsVectorTranslateOpts)
}

type createFeatureOpts struct {
errorHandler ErrorHandler
}

//CreateFeatureOption is an option that can be passed to Layer.CreateFeature
//
// Available options are:
// - none yet
type CreateFeatureOption interface {
setCreateFeatureOpt(cfo *createFeatureOpts)
}

type newFeatureOpts struct {
errorHandler ErrorHandler
}
Expand Down
6 changes: 3 additions & 3 deletions srs.go
Expand Up @@ -45,15 +45,15 @@ func (sr *SpatialRef) setBoundsOpt(o *boundsOpts) {
}

type boundsOpts struct {
sr *SpatialRef
//TODO: errorHandler ErrorHandler
sr *SpatialRef
errorHandler ErrorHandler
}

// BoundsOption is an option that can be passed to Dataset.Bounds or Geometry.Bounds
//
// Available options are:
// - *SpatialRef
// - TODO: ErrLogger
// - ErrLogger
type BoundsOption interface {
setBoundsOpt(o *boundsOpts)
}
Expand Down

0 comments on commit 548d787

Please sign in to comment.