fix: Fix geometry parsing
This commit is contained in:
@@ -33,7 +33,7 @@ type DatasetRepository interface {
|
||||
MarkParseFailed(ctx context.Context, id uuid.UUID, reason string) error
|
||||
MarkReady(ctx context.Context, id uuid.UUID) error
|
||||
MarkConverted(ctx context.Context, id uuid.UUID, cogKey string, footprint []byte) error
|
||||
SetProperties(ctx context.Context, id uuid.UUID, properties []byte) error
|
||||
SetProperties(ctx context.Context, id uuid.UUID, properties, geometry []byte) error
|
||||
SaveMapping(ctx context.Context, id uuid.UUID, katoColumn string, years []domain.YearColumn) (domain.Dataset, error)
|
||||
ReplaceObservations(ctx context.Context, datasetID uuid.UUID, obs []domain.Observation) error
|
||||
ListObservations(ctx context.Context, datasetID uuid.UUID, katoCode *string, limit, offset int) ([]domain.Observation, error)
|
||||
@@ -82,11 +82,15 @@ type ColumnParser func(filename string, data []byte) ([]domain.AttributeColumn,
|
||||
// RowParser reads every attribute row from a file's raw bytes as name->value maps.
|
||||
type RowParser func(filename string, data []byte) ([]map[string]string, error)
|
||||
|
||||
// RasterConverter converts a raster file to a Cloud-Optimized GeoTIFF and reads
|
||||
// its footprint. It operates on local file paths.
|
||||
// RasterConverter converts a raster file to a Cloud-Optimized GeoTIFF, reads its
|
||||
// footprint, and dissolves a vector file's features into a single geometry. It
|
||||
// operates on local file paths.
|
||||
type RasterConverter interface {
|
||||
ToCOG(ctx context.Context, srcPath, dstPath string) error
|
||||
Footprint(ctx context.Context, srcPath string) ([]byte, error)
|
||||
// VectorGeometry returns the combined geometry of a vector file's features as
|
||||
// GeoJSON in EPSG:4326 (nil if the file has no features).
|
||||
VectorGeometry(ctx context.Context, srcPath string) ([]byte, error)
|
||||
}
|
||||
|
||||
// UploadInput carries everything needed to store a new dataset.
|
||||
@@ -249,10 +253,12 @@ func (s *DatasetService) Reprocess(ctx context.Context, id uuid.UUID) (domain.Da
|
||||
return dataset, nil
|
||||
}
|
||||
|
||||
// ExtractProperties reads a plain vector dataset's attribute table and stores it
|
||||
// (as a JSON array of row objects) in the properties column, then marks the
|
||||
// dataset ready. Invoked by the worker. Parse failures are recorded; storage
|
||||
// failures are returned for retry.
|
||||
// ExtractProperties reads a plain vector dataset's attribute table and spatial
|
||||
// geometry and stores them (the attribute table as a JSON array of row objects
|
||||
// in the properties column, the dissolved feature geometry in the geometry
|
||||
// column), then marks the dataset ready. Invoked by the worker. Parse failures
|
||||
// are recorded; storage failures are returned for retry. Geometry extraction is
|
||||
// best-effort: a failure leaves geometry unset rather than failing the job.
|
||||
func (s *DatasetService) ExtractProperties(ctx context.Context, id uuid.UUID) error {
|
||||
dataset, err := s.repo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
@@ -278,7 +284,31 @@ func (s *DatasetService) ExtractProperties(ctx context.Context, id uuid.UUID) er
|
||||
return err
|
||||
}
|
||||
}
|
||||
return s.repo.SetProperties(ctx, id, properties)
|
||||
|
||||
geometry := s.vectorGeometry(ctx, dataset.Filename, data)
|
||||
return s.repo.SetProperties(ctx, id, properties, geometry)
|
||||
}
|
||||
|
||||
// vectorGeometry dissolves a vector file's features into a single GeoJSON
|
||||
// geometry via the converter. It writes the in-memory bytes to a temp file
|
||||
// (preserving the extension so the converter detects the format) because the
|
||||
// converter operates on file paths. Best-effort: any failure yields nil.
|
||||
func (s *DatasetService) vectorGeometry(ctx context.Context, filename string, data []byte) []byte {
|
||||
ext := strings.ToLower(filepath.Ext(filename))
|
||||
f, err := os.CreateTemp("", "gis-vec-*"+ext)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
if _, err := f.Write(data); err != nil {
|
||||
f.Close()
|
||||
return nil
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return nil
|
||||
}
|
||||
geom, _ := s.converter.VectorGeometry(ctx, f.Name())
|
||||
return geom
|
||||
}
|
||||
|
||||
// hasAttributeData reports whether any row carries at least one attribute.
|
||||
|
||||
Reference in New Issue
Block a user