From: Bborie Park Date: Mon, 14 Nov 2011 21:40:25 +0000 (+0000) Subject: Added ability to specify raster width and height to ST_Resample. X-Git-Tag: 2.0.0alpha1~707 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5bd86f0e991609fbc50d2449bd691e3fdd7b8ff2;p=postgis Added ability to specify raster width and height to ST_Resample. Associated ticket is #1267 git-svn-id: http://svn.osgeo.org/postgis/trunk@8153 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/raster/rt_core/rt_api.c b/raster/rt_core/rt_api.c index c6c6bb8a1..64cfd1cae 100644 --- a/raster/rt_core/rt_api.c +++ b/raster/rt_core/rt_api.c @@ -2,7 +2,7 @@ * $Id$ * * WKTRaster - Raster Types for PostGIS - * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage + * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011 Regents of the University of California * @@ -6793,15 +6793,25 @@ rt_raster_from_gdal_dataset(GDALDatasetH ds) { * * @param raster : raster to transform * @param src_srs : the raster's coordinate system in OGC WKT - * @param dst_srs : the warped raster's coordinate system - * @param scale_x : the pixel width of the warped raster - * @param scale_y : the pixel height of the warped raster - * @param ul_xw : the X value of upper-left corner of the warped raster - * @param ul_yw : the Y value of upper-left corner of the warped raster - * @param grid_xw : the X value of point on a grid to align warped raster to - * @param grid_yw : the Y value of point on a grid to align warped raster to - * @param skew_x : the X skew of the warped raster - * @param skew_y : the Y skew of the warped raster + * @param dst_srs : the warped raster's coordinate system in OGC WKT + * @param scale_x : the x size of pixels of the warped raster's pixels in + * units of dst_srs + * @param scale_y : the y size of pixels of the warped raster's pixels in + * units of dst_srs + * @param width : the number of columns of the warped raster. note that + * width/height CANNOT be used with scale_x/scale_y + * @param height : the number of rows of the warped raster. note that + * width/height CANNOT be used with scale_x/scale_y + * @param ul_xw : the X value of upper-left corner of the warped raster in + * units of dst_srs + * @param ul_yw : the Y value of upper-left corner of the warped raster in + * units of dst_srs + * @param grid_xw : the X value of point on a grid to align warped raster + * to in units of dst_srs + * @param grid_yw : the Y value of point on a grid to align warped raster + * to in units of dst_srs + * @param skew_x : the X skew of the warped raster in units of dst_srs + * @param skew_y : the Y skew of the warped raster in units of dst_srs * @param resample_alg : the resampling algorithm * @param max_err : maximum error measured in input pixels permitted * (0.0 for exact calculations) @@ -6812,6 +6822,7 @@ rt_raster rt_raster_gdal_warp( rt_raster raster, const char *src_srs, const char *dst_srs, double *scale_x, double *scale_y, + int *width, int *height, double *ul_xw, double *ul_yw, double *grid_xw, double *grid_yw, double *skew_x, double *skew_y, @@ -6840,8 +6851,8 @@ rt_raster rt_raster_gdal_warp( double dst_gt[6] = {0}; double dst_extent[4]; - int width = 0; - int height = 0; + int _width = 0; + int _height = 0; int ul_user = 0; double min_x = 0; double min_y = 0; @@ -6966,7 +6977,7 @@ rt_raster rt_raster_gdal_warp( /* get approximate output georeferenced bounds and resolution */ cplerr = GDALSuggestedWarpOutput2(src_ds, GDALGenImgProjTransform, - transform_arg, dst_gt, &width, &height, dst_extent, 0); + transform_arg, dst_gt, &_width, &_height, dst_extent, 0); GDALDestroyGenImgProjTransformer(transform_arg); if (cplerr != CE_None) { rterror("rt_raster_gdal_warp: Unable to get GDAL suggested warp output for output dataset creation\n"); @@ -7019,12 +7030,40 @@ rt_raster rt_raster_gdal_warp( if (NULL != skew_y) dst_gt[4] = *skew_y; + /* scale and width/height are mutually exclusive */ + if ( + ((NULL != scale_x) || (NULL != scale_y)) && + ((NULL != width) || (NULL != height)) + ) { + rterror("rt_raster_gdal_warp: Scale X/Y and width/height are mutually exclusive. Only provide one.\n"); + + GDALClose(src_ds); + + for (i = 0; i < transform_opts_len; i++) rtdealloc(transform_opts[i]); + rtdealloc(transform_opts); + + GDALDeregisterDriver(src_drv); + GDALDestroyDriver(src_drv); + + return NULL; + } + + /* user-defined width/height */ + if ((NULL != width) && (*width > 0.)) { + _width = *width; + dst_gt[1] = (dst_extent[2] - dst_extent[0]) / ((double) _width); + pix_x = 0; + } + if ((NULL != height) && (*height > 0.)) { + _height = *height; + dst_gt[5] = -1 * fabs((dst_extent[3] - dst_extent[1]) / ((double) _height)); + pix_y = 0; + } + /* user-defined scale */ if ( - (NULL != scale_x) && - (FLT_NEQ(*scale_x, 0.0)) && - (NULL != scale_y) && - (FLT_NEQ(*scale_y, 0.0)) + ((NULL != scale_x) && (FLT_NEQ(*scale_x, 0.0))) && + ((NULL != scale_y) && (FLT_NEQ(*scale_y, 0.0))) ) { pix_x = fabs(*scale_x); pix_y = fabs(*scale_y); @@ -7112,14 +7151,24 @@ rt_raster rt_raster_gdal_warp( /* adjust width and height to account new upper left */ if (ul_user) { /* use suggested lower right corner */ - max_x = dst_gt[0] + dst_gt[1] * width; - min_y = dst_gt[3] + dst_gt[5] * height; + max_x = dst_gt[0] + dst_gt[1] * _width; + min_y = dst_gt[3] + dst_gt[5] * _height; + + /* user defined width */ + if ((NULL != width) && (*width > 0.)) + grid_pix_x = fabs((max_x - min_x) / ((double) _width)); + else + _width = (int) ((max_x - min_x + (grid_pix_x / 2.)) / grid_pix_x); + + /* user defined height */ + if ((NULL != height) && (*height > 0.)) + grid_pix_y = fabs((max_y - min_y) / ((double) _height)); + else + _height = (int) ((max_y - min_y + (grid_pix_y / 2.)) / grid_pix_y); - width = (int) ((max_x - min_x + (grid_pix_x / 2.)) / grid_pix_x); - height = (int) ((max_y - min_y + (grid_pix_y / 2.)) / grid_pix_y); dst_gt[1] = grid_pix_x; dst_gt[5] = -1 * grid_pix_y; - RASTER_DEBUGF(3, "new dimensions: %d x %d", width, height); + RASTER_DEBUGF(3, "new dimensions: %d x %d", _width, _height); } RASTER_DEBUGF(3, "shift is: %f, %f", grid_shift_xw, grid_shift_yw); @@ -7144,15 +7193,17 @@ rt_raster rt_raster_gdal_warp( } /* lower-right corner */ - max_x = min_x + dst_gt[1] * width; - min_y = max_y + dst_gt[5] * height; + max_x = min_x + dst_gt[1] * _width; + min_y = max_y + dst_gt[5] * _height; - width = (int) ((max_x - min_x + (pix_x / 2.)) / pix_x); - height = (int) ((max_y - min_y + (pix_y / 2.)) / pix_y); + _width = (int) ((max_x - min_x + (pix_x / 2.)) / pix_x); + _height = (int) ((max_y - min_y + (pix_y / 2.)) / pix_y); dst_gt[0] = min_x; dst_gt[3] = max_y; dst_gt[1] = pix_x; dst_gt[5] = -1 * pix_y; + + RASTER_DEBUGF(3, "new dimensions: %d x %d", _width, _height); } /* user-defined upper-left corner */ else if (ul_user) { @@ -7163,10 +7214,10 @@ rt_raster rt_raster_gdal_warp( RASTER_DEBUGF(3, "Applied geotransform: %f, %f, %f, %f, %f, %f", dst_gt[0], dst_gt[1], dst_gt[2], dst_gt[3], dst_gt[4], dst_gt[5]); RASTER_DEBUGF(3, "Raster dimensions (width x height): %d x %d", - width, height); + _width, _height); - if (FLT_EQ(width, 0.0) || FLT_EQ(height, 0.0)) { - rterror("rt_raster_gdal_warp: The width (%f) or height (%f) of the warped raster is zero\n", width, height); + if (FLT_EQ(_width, 0.0) || FLT_EQ(_height, 0.0)) { + rterror("rt_raster_gdal_warp: The width (%f) or height (%f) of the warped raster is zero\n", _width, _height); GDALClose(src_ds); @@ -7194,7 +7245,7 @@ rt_raster rt_raster_gdal_warp( } /* create dst dataset */ - dst_ds = GDALCreate(dst_drv, "", width, height, 0, GDT_Byte, dst_options); + dst_ds = GDALCreate(dst_drv, "", _width, _height, 0, GDT_Byte, dst_options); if (NULL == dst_ds) { rterror("rt_raster_gdal_warp: Unable to create GDAL VRT dataset\n"); diff --git a/raster/rt_core/rt_api.h b/raster/rt_core/rt_api.h index 0e7652d70..ba12d2d9c 100644 --- a/raster/rt_core/rt_api.h +++ b/raster/rt_core/rt_api.h @@ -1040,15 +1040,25 @@ rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds); * * @param raster : raster to transform * @param src_srs : the raster's coordinate system in OGC WKT - * @param dst_srs : the warped raster's coordinate system - * @param scale_x : the pixel width of the warped raster - * @param scale_y : the pixel height of the warped raster - * @param ul_xw : the X value of upper-left corner of the warped raster - * @param ul_yw : the Y value of upper-left corner of the warped raster - * @param grid_xw : the X value of point on a grid to align warped raster to - * @param grid_yw : the Y value of point on a grid to align warped raster to - * @param skew_x : the X skew of the warped raster - * @param skew_y : the Y skew of the warped raster + * @param dst_srs : the warped raster's coordinate system in OGC WKT + * @param scale_x : the x size of pixels of the warped raster's pixels in + * units of dst_srs + * @param scale_y : the y size of pixels of the warped raster's pixels in + * units of dst_srs + * @param width : the number of columns of the warped raster. note that + * width/height CANNOT be used with scale_x/scale_y + * @param height : the number of rows of the warped raster. note that + * width/height CANNOT be used with scale_x/scale_y + * @param ul_xw : the X value of upper-left corner of the warped raster in + * units of dst_srs + * @param ul_yw : the Y value of upper-left corner of the warped raster in + * units of dst_srs + * @param grid_xw : the X value of point on a grid to align warped raster + * to in units of dst_srs + * @param grid_yw : the Y value of point on a grid to align warped raster + * to in units of dst_srs + * @param skew_x : the X skew of the warped raster in units of dst_srs + * @param skew_y : the Y skew of the warped raster in units of dst_srs * @param resample_alg : the resampling algorithm * @param max_err : maximum error measured in input pixels permitted * (0.0 for exact calculations) @@ -1058,6 +1068,7 @@ rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds); rt_raster rt_raster_gdal_warp(rt_raster raster, const char *src_srs, const char *dst_srs, double *scale_x, double *scale_y, + int *width, int *height, double *ul_xw, double *ul_yw, double *grid_xw, double *grid_yw, double *skew_x, double *skew_y, diff --git a/raster/rt_pg/rt_pg.c b/raster/rt_pg/rt_pg.c index 151ed352b..15ecaccb3 100644 --- a/raster/rt_pg/rt_pg.c +++ b/raster/rt_pg/rt_pg.c @@ -6738,13 +6738,15 @@ Datum RASTER_asRaster(PG_FUNCTION_ARGS) /* width */ if (!PG_ARGISNULL(3)) { dim[0] = PG_GETARG_INT32(3); - if (FLT_NEQ(dim[0], 0)) dim_x = &dim[0]; + if (dim[0] < 0) dim[0] = 0; + if (dim[0] != 0) dim_x = &dim[0]; } /* height */ if (!PG_ARGISNULL(4)) { dim[1] = PG_GETARG_INT32(4); - if (FLT_NEQ(dim[1], 0)) dim_y = &dim[1]; + if (dim[1] < 0) dim[1] = 0; + if (dim[1] != 0) dim_y = &dim[1]; } POSTGIS_RT_DEBUGF(3, "RASTER_asRaster: dim (x, y) = %d, %d", dim[0], dim[1]); @@ -7253,6 +7255,10 @@ Datum RASTER_resample(PG_FUNCTION_ARGS) double *skew_x = NULL; double *skew_y = NULL; + int dim[2] = {0}; + int *dim_x = NULL; + int *dim_y = NULL; + POSTGIS_RT_DEBUG(3, "RASTER_resample: Starting"); /* pgraster is null, return null */ @@ -7339,6 +7345,20 @@ Datum RASTER_resample(PG_FUNCTION_ARGS) if (FLT_NEQ(skew[1], 0)) skew_y = &skew[1]; } + /* width */ + if (!PG_ARGISNULL(10)) { + dim[0] = PG_GETARG_INT32(10); + if (dim[0] < 0) dim[0] = 0; + if (dim[0] > 0) dim_x = &dim[0]; + } + + /* height */ + if (!PG_ARGISNULL(11)) { + dim[1] = PG_GETARG_INT32(11); + if (dim[1] < 0) dim[1] = 0; + if (dim[1] > 0) dim_y = &dim[1]; + } + /* check that at least something is to be done */ if ( (clamp_srid(dst_srid) == SRID_UNKNOWN) && @@ -7347,7 +7367,9 @@ Datum RASTER_resample(PG_FUNCTION_ARGS) (grid_xw == NULL) && (grid_yw == NULL) && (skew_x == NULL) && - (skew_y == NULL) + (skew_y == NULL) && + (dim_x == NULL) && + (dim_y == NULL) ) { elog(NOTICE, "No resampling parameters provided. Returning original raster"); rt_raster_destroy(raster); @@ -7371,6 +7393,15 @@ Datum RASTER_resample(PG_FUNCTION_ARGS) rt_raster_destroy(raster); PG_RETURN_POINTER(pgraster); } + /* scale and width/height provided */ + else if ( + (scale_x != NULL || scale_y != NULL) && + (dim_x != NULL || dim_y != NULL) + ) { + elog(NOTICE, "Scale X/Y and width/height are mutually exclusive. Only provide one. Returning original raster"); + rt_raster_destroy(raster); + PG_RETURN_POINTER(pgraster); + } /* get srses from srids */ /* source srs */ @@ -7397,6 +7428,7 @@ Datum RASTER_resample(PG_FUNCTION_ARGS) rast = rt_raster_gdal_warp(raster, src_srs, dst_srs, scale_x, scale_y, + dim_x, dim_y, NULL, NULL, grid_xw, grid_yw, skew_x, skew_y, diff --git a/raster/rt_pg/rtpostgis.sql.in.c b/raster/rt_pg/rtpostgis.sql.in.c index ae27e0899..8c48fbd48 100644 --- a/raster/rt_pg/rtpostgis.sql.in.c +++ b/raster/rt_pg/rtpostgis.sql.in.c @@ -1484,7 +1484,8 @@ CREATE OR REPLACE FUNCTION _st_resample( srid integer DEFAULT NULL, scalex double precision DEFAULT 0, scaley double precision DEFAULT 0, gridx double precision DEFAULT NULL, gridy double precision DEFAULT NULL, - skewx double precision DEFAULT 0, skewy double precision DEFAULT 0 + skewx double precision DEFAULT 0, skewy double precision DEFAULT 0, + width integer DEFAULT NULL, height integer DEFAULT NULL ) RETURNS raster AS 'MODULE_PATHNAME', 'RASTER_resample' @@ -1502,16 +1503,31 @@ CREATE OR REPLACE FUNCTION st_resample( AS $$ SELECT _st_resample($1, $9, $10, $2, $3, $4, $5, $6, $7, $8) $$ LANGUAGE 'sql' STABLE; +CREATE OR REPLACE FUNCTION st_resample( + rast raster, + width integer, height integer, + srid integer DEFAULT NULL, + gridx double precision DEFAULT NULL, gridy double precision DEFAULT NULL, + skewx double precision DEFAULT 0, skewy double precision DEFAULT 0, + algorithm text DEFAULT 'NearestNeighbour', maxerr double precision DEFAULT 0.125 +) + RETURNS raster + AS $$ SELECT _st_resample($1, $9, $10, $4, NULL, NULL, $5, $6, $7, $8, $2, $3) $$ + LANGUAGE 'sql' STABLE; + CREATE OR REPLACE FUNCTION st_resample( rast raster, ref raster, algorithm text DEFAULT 'NearestNeighbour', - maxerr double precision DEFAULT 0.125 + maxerr double precision DEFAULT 0.125, + usescale boolean DEFAULT TRUE ) RETURNS raster AS $$ DECLARE sr_id int; + dim_x int; + dim_y int; scale_x double precision; scale_y double precision; grid_x double precision; @@ -1519,11 +1535,31 @@ CREATE OR REPLACE FUNCTION st_resample( skew_x double precision; skew_y double precision; BEGIN - SELECT srid, scalex, scaley, upperleftx, upperlefty, skewx, skewy INTO sr_id, scale_x, scale_y, grid_x, grid_y, skew_x, skew_y FROM st_metadata($2); - RETURN _st_resample($1, $3, $4, sr_id, scale_x, scale_y, grid_x, grid_y, skew_x, skew_y); + SELECT srid, width, height, scalex, scaley, upperleftx, upperlefty, skewx, skewy INTO sr_id, dim_x, dim_y, scale_x, scale_y, grid_x, grid_y, skew_x, skew_y FROM st_metadata($2); + + IF usescale IS TRUE THEN + dim_x := NULL; + dim_y := NULL; + ELSE + scale_x := NULL; + scale_y := NULL; + END IF; + + RETURN _st_resample($1, $3, $4, sr_id, scale_x, scale_y, grid_x, grid_y, skew_x, skew_y, dim_x, dim_y); END; $$ LANGUAGE 'plpgsql' STABLE STRICT; +CREATE OR REPLACE FUNCTION st_resample( + rast raster, + ref raster, + usescale boolean, + algorithm text DEFAULT 'NearestNeighbour', + maxerr double precision DEFAULT 0.125 +) + RETURNS raster + AS $$ SELECT st_resample($1, $2, $4, $5, $3) $$ + LANGUAGE 'sql' STABLE STRICT; + ----------------------------------------------------------------------- -- ST_Transform ----------------------------------------------------------------------- diff --git a/raster/rt_pg/rtpostgis_drop.sql.in.c b/raster/rt_pg/rtpostgis_drop.sql.in.c index 188871599..d29a4b883 100644 --- a/raster/rt_pg/rtpostgis_drop.sql.in.c +++ b/raster/rt_pg/rtpostgis_drop.sql.in.c @@ -76,6 +76,9 @@ DROP FUNCTION IF EXISTS _ST_AsRaster(geometry,double precision , double precisio -- arg names changed DROP FUNCTION IF EXISTS _ST_Resample(raster, text, double precision, integer, double precision, double precision, double precision, double precision, double precision, double precision); +-- signature changed +DROP FUNCTION IF EXISTS ST_Resample(raster, raster, text, double precision); + -- default parameters added DROP FUNCTION IF EXISTS ST_HasNoBand(raster); diff --git a/raster/test/core/testapi.c b/raster/test/core/testapi.c index a6e5d9ffd..b704aeb35 100644 --- a/raster/test/core/testapi.c +++ b/raster/test/core/testapi.c @@ -1524,6 +1524,7 @@ static void testGDALWarp() { NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, GRA_NearestNeighbour, -1 ); CHECK(rast); diff --git a/raster/test/regress/rt_resample.sql b/raster/test/regress/rt_resample.sql index d76cf7757..408a22046 100644 --- a/raster/test/regress/rt_resample.sql +++ b/raster/test/regress/rt_resample.sql @@ -69,7 +69,7 @@ INSERT INTO raster_resample_dst (rid, rast) VALUES ( 1.5, (SELECT ST_Resample( rast, 993310, - 500, 500, + 500., 500., NULL, NULL, 0, 0, 'NearestNeighbor', 0.125 @@ -78,25 +78,25 @@ INSERT INTO raster_resample_dst (rid, rast) VALUES ( 1.6, (SELECT ST_Resample( rast, NULL, - 100, NULL + 100., NULL ) FROM raster_resample_src) ), ( 1.7, (SELECT ST_Resample( rast, NULL, - NULL::double precision, 100 + NULL::double precision, 100. ) FROM raster_resample_src) ), ( 1.8, (SELECT ST_Resample( rast, NULL, - 500, 500 + 500., 500. ) FROM raster_resample_src) ), ( 1.9, (SELECT ST_Resample( rast, NULL, - 250, 250, + 250., 250., NULL, NULL, NULL, NULL ) FROM raster_resample_src) @@ -104,7 +104,7 @@ INSERT INTO raster_resample_dst (rid, rast) VALUES ( 1.10, (SELECT ST_Resample( rast, NULL, - 250, 250, + 250., 250., NULL, NULL, NULL, NULL, 'Bilinear', 0 @@ -141,28 +141,28 @@ INSERT INTO raster_resample_dst (rid, rast) VALUES ( 1.15, (SELECT ST_Resample( rast, NULL, - 50, 50, + 50., 50., -290, 7 ) FROM raster_resample_src) ), ( 1.16, (SELECT ST_Resample( rast, NULL, - 121, 121, + 121., 121., 0, 0 ) FROM raster_resample_src) ), ( 1.17, (SELECT ST_Resample( rast, 993310, - 50, 50, + 50., 50., -290, 7 ) FROM raster_resample_src) ), ( 1.18, (SELECT ST_Resample( rast, 993309, - 50, 50, + 50., 50., -290, 7 ) FROM raster_resample_src) ), ( @@ -195,7 +195,7 @@ INSERT INTO raster_resample_dst (rid, rast) VALUES ( 1.22, (SELECT ST_Resample( rast, 993310, - 500, 500, + 500., 500., NULL, NULL, 3, 3, 'Cubic', 0 @@ -204,7 +204,7 @@ INSERT INTO raster_resample_dst (rid, rast) VALUES ( 1.23, (SELECT ST_Resample( rast, 993310, - 500, 500, + 500., 500., -12048, 14682, 0, 6, 'CubicSpline' @@ -214,6 +214,29 @@ INSERT INTO raster_resample_dst (rid, rast) VALUES ( rast, ST_MakeEmptyRaster(5, 5, -654321, 123456, 50, -100, 3, 0, 992163) ) FROM raster_resample_src) +), ( + 1.25, (SELECT ST_Resample( + rast, + ST_MakeEmptyRaster(5, 5, -654321, 123456, 50, -100, 3, 0, 992163), + TRUE + ) FROM raster_resample_src) +), ( + 1.26, (SELECT ST_Resample( + rast, + 150, 150 + ) FROM raster_resample_src) +), ( + 1.27, (SELECT ST_Resample( + rast, + 150, 150, + 993310 + ) FROM raster_resample_src) +), ( + 1.28, (SELECT ST_Resample( + rast, + ST_MakeEmptyRaster(5, 5, -654321, 123456, 100, 100, 0, 0, 992163), + FALSE + ) FROM raster_resample_src) ); -- ST_Transform diff --git a/raster/test/regress/rt_resample_expected b/raster/test/regress/rt_resample_expected index 6744635c0..34e99eef5 100644 --- a/raster/test/regress/rt_resample_expected +++ b/raster/test/regress/rt_resample_expected @@ -19,6 +19,10 @@ NOTICE: Values must be provided for both X and Y when specifying the scale. Re 1.22|993310|24|24|1|500.000|-500.000|3.000|3.000|950732.188|1409281.783|t|t|t 1.23|993310|25|25|1|500.000|-500.000|0.000|6.000|950452.000|1409682.000|t|t|t 1.24|992163|200|101|1|50.000|-100.000|3.000|0.000|-500021.000|600056.000|t|t|t +1.25|992163|200|101|1|50.000|-100.000|3.000|0.000|-500021.000|600056.000|t|t|t +1.26|992163|150|150|1|66.667|-66.667|0.000|0.000|-500000.000|600000.000|t|t|t +1.27|993310|150|150|1|80.792|-80.792|0.000|0.000|950732.188|1409281.783|t|t|t +1.28|992163|5|5|1|2064.200|-2291.200|0.000|0.000|-500321.000|601456.000|t|t|t 1.3|993309|12|12|1|1009.916|-1009.916|0.000|0.000|950762.305|1409088.896|t|t|t 1.4|994269|12|8|1|0.012|-0.012|0.000|0.000|-107.029|50.206|t|t|t 1.5|993310|24|24|1|500.000|-500.000|0.000|0.000|950732.188|1409281.783|t|t|t