changeset 2309:8e3050227a19

Add irregular dimension handling, nonspatial voxel-to-world transforms
author bert <bert>
date Mon, 04 Jul 2005 12:43:35 +0000
parents 7db0db114a67
children a438fa86baf0
files volume_io/Volumes/input_mnc.c volume_io/Volumes/volumes.c
diffstat 2 files changed, 257 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/volume_io/Volumes/input_mnc.c
+++ b/volume_io/Volumes/input_mnc.c
@@ -16,7 +16,7 @@
 #include  <minc.h>
 
 #ifndef lint
-static char rcsid[] = "$Header: /private-cvsroot/minc/volume_io/Volumes/input_mnc.c,v 1.65.2.1 2004-10-04 20:20:14 bert Exp $";
+static char rcsid[] = "$Header: /private-cvsroot/minc/volume_io/Volumes/input_mnc.c,v 1.65.2.2 2005-07-04 12:43:35 bert Exp $";
 #endif
 
 #define  INVALID_AXIS   -1
@@ -131,6 +131,9 @@
     int                 spatial_axis_indices[MAX_VAR_DIMS];
     minc_input_options  default_options;
     BOOLEAN             no_volume_data_type;
+    char                spacing_type[MI_MAX_ATTSTR_LEN+1];
+    double              *irr_starts[MAX_VAR_DIMS];
+    double              *irr_widths[MAX_VAR_DIMS];
 
     ALLOC( file, 1 );
 
@@ -298,6 +301,9 @@
         file_separations[d] = 1.0;
         start_position[d] = 0.0;
 
+        irr_starts[d] = NULL;
+        irr_widths[d] = NULL;
+
         if( spatial_dim_flags[d] )
         {
             dir_cosines[d][0] = 0.0;
@@ -344,6 +350,43 @@
                         (void) strcpy( prev_space_type, space_type );
                 }
             }
+            else if (!strcmp(MItime, file->dim_names[d])) {
+                /* For the moment this is implemented for time dimensions
+                 * only.
+                 */
+                miattgetstr(file->cdfid, dimvar, MIspacing,
+                            MI_MAX_ATTSTR_LEN+1, spacing_type);
+                if (!strcmp(spacing_type, MI_IRREGULAR)) {
+                    long start[1];
+                    long count[1];
+                    int i;
+
+                    irr_starts[d] = malloc(sizeof(Real) * file->sizes_in_file[d]);
+                    irr_widths[d] = malloc(sizeof(Real) * file->sizes_in_file[d]);
+
+                    start[0] = 0;
+                    count[0] = file->sizes_in_file[d];
+
+                    mivarget(file->cdfid, dimvar, start, count,
+                             NC_DOUBLE, MI_SIGNED, irr_starts[d]);
+
+                    dimvar = ncvarid(file->cdfid, MItime_width);
+                    if (dimvar < 0) {
+                        for (i = 0; i < count[0]; i++) {
+                            irr_widths[d][i] = file_separations[d];
+                        }
+                    }
+                    else {
+                        mivarget(file->cdfid, dimvar, start, count,
+                                 NC_DOUBLE, MI_SIGNED, irr_widths[d]);
+                    }
+                }
+                else {
+                    if( miattget1(file->cdfid, dimvar, MIstart, NC_DOUBLE,
+                                  (void *) (&start_position[d]) ) == MI_ERROR )
+                        start_position[d] = 0.0;
+                }
+            }
         }
 
         if( file->to_volume_index[d] == INVALID_AXIS )
@@ -362,6 +405,7 @@
                 set_volume_direction_unit_cosine( volume,
                                 file->to_volume_index[d], dir_cosines[d] );
             }
+
         }
     }
 
@@ -410,6 +454,24 @@
 
     set_volume_sizes( volume, sizes );
 
+    for_less( d, 0, file->n_file_dimensions ) 
+    {
+        if (file->to_volume_index[d] == INVALID_AXIS) {
+            continue;
+        }
+
+        if (irr_starts[d] != NULL) {
+            set_volume_irregular_starts(volume, file->to_volume_index[d],
+                                        file->sizes_in_file[d],
+                                        irr_starts[d]);
+        }
+        if (irr_widths[d] != NULL) {
+            set_volume_irregular_widths(volume, file->to_volume_index[d],
+                                        file->sizes_in_file[d],
+                                        irr_widths[d]);
+        }
+    }
+                                        
     /* --- create the image conversion variable */
 
     file->minc_icv = miicv_create();
--- a/volume_io/Volumes/volumes.c
+++ b/volume_io/Volumes/volumes.c
@@ -17,7 +17,7 @@
 #include  <float.h>
 
 #ifndef lint
-static char rcsid[] = "$Header: /private-cvsroot/minc/volume_io/Volumes/volumes.c,v 1.72.2.1 2004-10-04 20:20:14 bert Exp $";
+static char rcsid[] = "$Header: /private-cvsroot/minc/volume_io/Volumes/volumes.c,v 1.72.2.2 2005-07-04 12:43:36 bert Exp $";
 #endif
 
 STRING   XYZ_dimension_names[] = { MIxspace, MIyspace, MIzspace };
@@ -187,6 +187,8 @@
         volume->direction_cosines[i][X] = 0.0;
         volume->direction_cosines[i][Y] = 0.0;
         volume->direction_cosines[i][Z] = 0.0;
+        volume->irregular_starts[i] = NULL;
+        volume->irregular_widths[i] = NULL;
 
         sizes[i] = 0;
 
@@ -2335,6 +2337,19 @@
 
     set_volume_space_type( copy, volume->coordinate_system_name );
 
+    for_less( c, 0, get_volume_n_dimensions(volume) )
+    {
+        if (is_volume_dimension_irregular(volume, c)) {
+            Real *irr_starts = malloc(sizeof(Real) * sizes[c]);
+            Real *irr_widths = malloc(sizeof(Real) * sizes[c]);
+            get_volume_irregular_starts( volume, c, sizes[c], irr_starts);
+            set_volume_irregular_starts( volume, c, sizes[c], irr_starts);
+
+            get_volume_irregular_widths( volume, c, sizes[c], irr_starts);
+            set_volume_irregular_widths( volume, c, sizes[c], irr_starts);
+        }
+    }
+
     return( copy );
 }
 
@@ -2424,3 +2439,181 @@
 
     return( copy );
 }
+
+/* These are not public functions, so they are not VIOAPI yet */
+BOOLEAN 
+is_volume_dimension_irregular(Volume volume, int idim)
+{
+    if (idim > volume->array.n_dimensions) {
+        return (0);
+    }
+    return (volume->irregular_starts[idim] != NULL);
+}
+
+int
+get_volume_irregular_starts(Volume volume, int idim, int count, Real *starts)
+{
+    int i;
+
+    if (idim >= volume->array.n_dimensions) {
+        return (0);
+    }
+
+    if (volume->irregular_starts[idim] == NULL) {
+        return (0);
+    }
+
+    if (count > volume->array.sizes[idim]) {
+        count = volume->array.sizes[idim];
+    }
+
+    for (i = 0; i < count; i++) {
+        starts[i] = volume->irregular_starts[idim][i];
+    }
+
+    return (count);
+}
+
+int
+get_volume_irregular_widths(Volume volume, int idim, int count, Real *widths)
+{
+    int i;
+
+    if (idim >= volume->array.n_dimensions) {
+        return (0);
+    }
+
+    if (volume->irregular_widths[idim] == NULL) {
+        return (0);
+    }
+
+    if (count > volume->array.sizes[idim]) {
+        count = volume->array.sizes[idim];
+    }
+
+    for (i = 0; i < count; i++) {
+        widths[i] = volume->irregular_widths[idim][i];
+    }
+
+    return (count);
+}
+
+int
+set_volume_irregular_starts(Volume volume, int idim, int count, Real *starts)
+{
+    int i;
+
+    if (idim >= volume->array.n_dimensions) {
+        return (0);
+    }
+
+    if (volume->irregular_starts[idim] != NULL) {
+        free(volume->irregular_starts[idim]);
+    }
+
+    if (starts == NULL) {
+        return (0);
+    }
+
+    if (count > volume->array.sizes[idim]) {
+        count = volume->array.sizes[idim];
+    }
+
+    volume->irregular_starts[idim] = malloc(count * sizeof (Real));
+    if (volume->irregular_starts[idim] == NULL) {
+        return (0);
+    }
+
+    for (i = 0; i < count; i++) {
+        volume->irregular_starts[idim][i] = starts[i];
+    }
+
+    return (count);
+}
+
+int
+set_volume_irregular_widths(Volume volume, int idim, int count, Real *widths)
+{
+    int i;
+
+    if (idim >= volume->array.n_dimensions) {
+        return (0);
+    }
+
+    if (volume->irregular_widths[idim] != NULL) {
+        free(volume->irregular_widths[idim]);
+    }
+
+    if (widths == NULL) {
+        return (0);
+    }
+
+    if (count > volume->array.sizes[idim]) {
+        count = volume->array.sizes[idim];
+    }
+
+    volume->irregular_widths[idim] = malloc(count * sizeof (Real));
+    if (volume->irregular_widths[idim] == NULL) {
+        return (0);
+    }
+
+    for (i = 0; i < count; i++) {
+        volume->irregular_widths[idim][i] = widths[i];
+    }
+
+    return (count);
+}
+
+
+VIOAPI VIO_Real
+nonspatial_voxel_to_world(Volume volume, int idim, int voxel)
+{
+    VIO_Real world;
+
+    if (is_volume_dimension_irregular(volume, idim)) {
+        if (voxel < 0) {
+            world = 0.0;
+        }
+        else if (voxel >= volume->array.sizes[idim]) {
+            /* If we are asking for a position PAST the end of the axis,
+             * return the very last position on the axis, defined as the
+             * last start position plus the last width.
+             * NOTE! TODO: FIXME! We should take the axis alignment into
+             * account here.
+             */
+            voxel = volume->array.sizes[idim] - 1;
+
+            world = (volume->irregular_starts[idim][voxel] + 
+                     volume->irregular_widths[idim][voxel]);
+        }
+        else {
+            world = volume->irregular_starts[idim][voxel];
+        }
+    }
+    else {
+        world = volume->starts[idim] + (voxel * volume->separations[idim]);
+    }
+    return (world);
+}
+
+VIOAPI int
+nonspatial_world_to_voxel(Volume volume, int idim, VIO_Real world)
+{
+    int voxel;
+    int i;
+
+    if (is_volume_dimension_irregular(volume, idim)) {
+        voxel = volume->array.sizes[idim];
+        for (i = 0; i < volume->array.sizes[idim]; i++) {
+            if (world < (volume->irregular_starts[idim][i] + 
+                         volume->irregular_widths[idim][i])) {
+                voxel = i;
+                break;
+            }
+        }
+    }
+    else {
+        voxel = ROUND((world - volume->starts[idim]) / volume->separations[idim]);
+    }
+    return (voxel);
+}