/** * @brief Remove all boxes from cubical volume - service callback function * @param req Request * @param res Response */ bool srs_env_model::CCMapPlugin::addBoxCallback( srs_env_model::RemoveCube::Request & req, srs_env_model::RemoveCube::Response & res ) { // Test frame id if (req.frame_id != m_cmapFrameId) { // Transform size geometry_msgs::PointStamped vs, vsout; vs.header.frame_id = req.frame_id; vs.header.stamp = m_mapTime; POINT_ADD( vs.point, req.size, req.pose.position ); m_tfListener.transformPoint(m_cmapFrameId, vs, vsout); // Transform pose geometry_msgs::PoseStamped ps, psout; ps.header.frame_id = req.frame_id; ps.header.stamp = m_mapTime; ps.pose = req.pose; m_tfListener.transformPose(m_cmapFrameId, ps, psout); req.pose = psout.pose; // Finalize size transform POINT_SUB(req.size, vsout.point, psout.pose.position); POINT_ABS(req.size, req.size); } tBoxPoint center, size; // Convert point type center.x = req.pose.position.x; center.y = req.pose.position.y; center.z = req.pose.position.z; size.x = req.size.x; size.y = req.size.y; size.z = req.size.z; // Add box // std::cerr << "Adding box. " << m_data->boxes.size() << " -> "; addBox( center, size, m_data->boxes ); // std::cerr << m_data->boxes.size() << std::endl; invalidate(); return true; }
/* returns a slice with the appropriate data from the data_set */ AmitkDataSet * amitk_data_set_DOUBLE_0D_SCALING_get_slice(AmitkDataSet * data_set, const amide_time_t start_time, const amide_time_t duration, const amide_intpoint_t gate, const AmitkCanvasPoint pixel_size, const AmitkVolume * slice_volume) { /* zp_start, where on the zp axis to start the slice, zp (z_prime) corresponds to the rotated axises, if negative, choose the midpoint */ AmitkDataSet * slice = NULL; AmitkVoxel i_voxel; amide_intpoint_t z; amide_real_t max_diff, voxel_length, z_steps; AmitkPoint alt; AmitkPoint stride[AMITK_AXIS_NUM], last[AMITK_AXIS_NUM]; AmitkAxis i_axis; guint k, l; amide_data_t weight; amide_data_t time_weight; amide_intpoint_t start_frame, end_frame; amide_intpoint_t i_gate; amide_time_t end_time; AmitkPoint box_point[8]; AmitkVoxel box_voxel[8]; AmitkVoxel start, end; amide_data_t box_value[8]; AmitkPoint slice_point, ds_point,start_point,diff, nearest_point; AmitkSpace * slice_space; AmitkSpace * data_set_space; #if AMIDE_DEBUG gchar * temp_string; AmitkPoint center_point; #endif AmitkVoxel ds_voxel; amide_data_t weight1, weight2; amide_data_t * weights=NULL; amide_data_t * intermediate_data=NULL; AmitkCorners intersection_corners; AmitkVoxel dim; gint num_gates; gboolean empties=FALSE; /* ----- figure out what frames of this data set to include ----*/ end_time = start_time+duration; start_frame = amitk_data_set_get_frame(data_set, start_time+EPSILON); end_frame = amitk_data_set_get_frame(data_set, end_time-EPSILON); /* the number of gates we'll be looking at */ if (gate < 0) num_gates = AMITK_DATA_SET_NUM_VIEW_GATES(data_set); else num_gates = 1; /* ------------------------- */ dim.x = ceil(fabs(AMITK_VOLUME_X_CORNER(slice_volume))/pixel_size.x); dim.y = ceil(fabs(AMITK_VOLUME_Y_CORNER(slice_volume))/pixel_size.y); dim.z = dim.g = dim.t = 1; /* if we need it, get the weighting matrix */ if (data_set->rendering == AMITK_RENDERING_MPR) { if ((weights = g_try_malloc0(sizeof(amide_data_t)*dim.x*dim.y)) == NULL) { g_warning(_("couldn't allocate memory space for the weights, wanted %dx%d elements"), dim.x, dim.y); goto error; } } /* get an intermediate data matrix to speed things up */ if ((intermediate_data = g_try_malloc0(sizeof(amide_data_t)*dim.x*dim.y)) == NULL) { g_warning(_("couldn't allocate memory space for the intermediate_data, wanted %dx%d elements"), dim.x, dim.y); goto error; } /* get the return slice */ slice = amitk_data_set_new_with_data(NULL, AMITK_DATA_SET_MODALITY(data_set), AMITK_FORMAT_DOUBLE, dim, AMITK_SCALING_TYPE_0D); if (slice == NULL) { g_warning(_("couldn't allocate memory space for the slice, wanted %dx%dx%d elements"), dim.x, dim.y, dim.z); goto error; } slice->slice_parent = data_set; g_object_add_weak_pointer(G_OBJECT(data_set), (gpointer *) &(slice->slice_parent)); slice->voxel_size.x = pixel_size.x; slice->voxel_size.y = pixel_size.y; slice->voxel_size.z = AMITK_VOLUME_Z_CORNER(slice_volume); amitk_space_copy_in_place(AMITK_SPACE(slice), AMITK_SPACE(slice_volume)); slice->scan_start = start_time; slice->thresholding = data_set->thresholding; slice->interpolation = AMITK_DATA_SET_INTERPOLATION(data_set); slice->rendering = AMITK_DATA_SET_RENDERING(data_set); if (gate < 0) { slice->view_start_gate = AMITK_DATA_SET_VIEW_START_GATE(data_set); slice->view_end_gate = AMITK_DATA_SET_VIEW_END_GATE(data_set); } else { slice->view_start_gate = gate; slice->view_end_gate = gate; } amitk_data_set_calc_far_corner(slice); amitk_data_set_set_frame_duration(slice, 0, duration); #if AMIDE_DEBUG center_point = amitk_volume_get_center(slice_volume); temp_string = g_strdup_printf("slice from data_set %s: @ x %5.3f y %5.3f z %5.3f", AMITK_OBJECT_NAME(data_set), center_point.x, center_point.y, center_point.z); amitk_object_set_name(AMITK_OBJECT(slice),temp_string); g_free(temp_string); #endif #ifdef AMIDE_DEBUG_COMMENT_OUT { AmitkCorners real_corner; /* convert to real space */ real_corner[0] = AMITK_SPACE_OFFSET(slice); real_corner[1] = amitk_space_s2b(AMITK_SPACE(slice), AMITK_VOLUME_CORNER(slice)); g_print("new slice from data_set %s\t---------------------\n",AMITK_OBJECT_NAME(data_set)); g_print("\tdim\t\tx %d\t\ty %d\t\tz %d\n", dim.x, dim.y, dim.z); g_print("\treal corner[0]\tx %5.4f\ty %5.4f\tz %5.4f\n", real_corner[0].x,real_corner[0].y,real_corner[0].z); g_print("\treal corner[1]\tx %5.4f\ty %5.4f\tz %5.4f\n", real_corner[1].x,real_corner[1].y,real_corner[1].z); g_print("\tdata set\t\tstart\t%5.4f\tend\t%5.3f\tframes %d to %d\n", start_time, end_time,start_frame,end_frame); } #endif /* get direct pointers to the slice's and data set's spaces for efficiency */ slice_space = AMITK_SPACE(slice); data_set_space = AMITK_SPACE(data_set); /* voxel_length is the length of a voxel given the coordinate frame of the slice. this is used to figure out how many iterations in the z direction we need to do */ alt.x = alt.y = 0.0; alt.z = 1.0; alt = amitk_space_s2s_dim(slice_space, data_set_space, alt); alt = point_mult(alt, data_set->voxel_size); voxel_length = POINT_MAGNITUDE(alt); z_steps = slice->voxel_size.z/voxel_length; /* non-integer */ /* figure out the intersection bounds between the data set and the requested slice volume */ if (amitk_volume_volume_intersection_corners(slice_volume, AMITK_VOLUME(data_set), intersection_corners)) { /* translate the intersection into voxel space */ POINT_TO_VOXEL(intersection_corners[0], slice->voxel_size, 0, 0, start); POINT_TO_VOXEL(intersection_corners[1], slice->voxel_size, 0, 0, end); } else { /* no intersection */ start = zero_voxel; end = zero_voxel; } /* make sure we only iterate over the slice we've already malloc'ed */ if (start.x < 0) start.x = 0; if (start.y < 0) start.y = 0; if (end.x >= dim.x) end.x = dim.x-1; if (end.y >= dim.y) end.y = dim.y-1; /* iterate over those voxels that we won't be covering, and mark them as NAN */ i_voxel.t = i_voxel.g = i_voxel.z = 0; for (i_voxel.y = 0; i_voxel.y < start.y; i_voxel.y++) for (i_voxel.x = 0; i_voxel.x < dim.x; i_voxel.x++) AMITK_RAW_DATA_DOUBLE_SET_CONTENT(slice->raw_data,i_voxel) = NAN; for (i_voxel.y = end.y+1; i_voxel.y < dim.y; i_voxel.y++) for (i_voxel.x = 0; i_voxel.x < dim.x; i_voxel.x++) AMITK_RAW_DATA_DOUBLE_SET_CONTENT(slice->raw_data,i_voxel) = NAN; for (i_voxel.x = 0; i_voxel.x < start.x; i_voxel.x++) for (i_voxel.y = 0; i_voxel.y < dim.y; i_voxel.y++) AMITK_RAW_DATA_DOUBLE_SET_CONTENT(slice->raw_data,i_voxel) = NAN; for (i_voxel.x = end.x+1; i_voxel.x < dim.x; i_voxel.x++) for (i_voxel.y = 0; i_voxel.y < dim.y; i_voxel.y++) AMITK_RAW_DATA_DOUBLE_SET_CONTENT(slice->raw_data,i_voxel) = NAN; switch(data_set->interpolation) { case AMITK_INTERPOLATION_TRILINEAR: /* iterate over the frames we'll be incorporating into this slice */ for (ds_voxel.t = start_frame; ds_voxel.t <= end_frame; ds_voxel.t++) { /* averaging over more then one frame */ if (end_frame-start_frame > 0) { if (ds_voxel.t == start_frame) time_weight = (amitk_data_set_get_end_time(data_set, start_frame)-start_time)/(duration*num_gates); else if (ds_voxel.t == end_frame) time_weight = (end_time-amitk_data_set_get_start_time(data_set, end_frame))/(duration*num_gates); else time_weight = amitk_data_set_get_frame_duration(data_set, ds_voxel.t)/(duration*num_gates); } else time_weight = 1.0/((gdouble) num_gates); for (i_gate=0; i_gate < num_gates; i_gate++) { if (gate < 0) ds_voxel.g = i_gate+AMITK_DATA_SET_VIEW_START_GATE(data_set); else ds_voxel.g = i_gate+gate; if (ds_voxel.g >= AMITK_DATA_SET_NUM_GATES(data_set)) ds_voxel.g -= AMITK_DATA_SET_NUM_GATES(data_set); /* initialize the .t/.g components of box_voxel */ for (l=0; l<8; l=l+1) { box_voxel[l].t = ds_voxel.t; box_voxel[l].g = ds_voxel.g; } /* iterate over the number of planes we'll be compressing into this slice */ for (z = 0; z < ceil(z_steps); z++) { /* the slices z_coordinate for this iteration's slice voxel */ if (ceil(z_steps) > 1.0) slice_point.z = (z+0.5)*voxel_length; else slice_point.z = (0.5)*slice->voxel_size.z; /* only one iteration in z */ /* weight is between 0 and 1, this is used to weight the last voxel in the slice's z direction */ if (floor(z_steps) > z) weight = time_weight/z_steps; else weight = time_weight*(z_steps-floor(z_steps)) / z_steps; /* iterate over the y dimension */ for (i_voxel.y = start.y,k=0; i_voxel.y <= end.y; i_voxel.y++) { /* the slice y_coordinate of the center of this iteration's slice voxel */ slice_point.y = (((amide_real_t) i_voxel.y)+0.5)*slice->voxel_size.y; /* the slice x coord of the center of the first slice voxel in this loop */ slice_point.x = (((amide_real_t) start.x)+0.5)*slice->voxel_size.x; /* iterate over the x dimension */ for (i_voxel.x = start.x; i_voxel.x <= end.x; i_voxel.x++,k++) { /* translate the current point in slice space into the data set's coordinate frame */ ds_point = amitk_space_s2s(slice_space, data_set_space, slice_point); /* get the nearest neighbor in the data set to this slice voxel */ POINT_TO_VOXEL_COORDS_ONLY(ds_point, data_set->voxel_size, ds_voxel); VOXEL_TO_POINT(ds_voxel, data_set->voxel_size, nearest_point); /* figure out which way to go to get the nearest voxels to our slice voxel*/ POINT_SUB(ds_point, nearest_point, diff); /* figure out which voxels to look at */ for (l=0; l<8; l=l+1) { if (diff.x < 0) box_voxel[l].x = (l & 0x1) ? ds_voxel.x-1 : ds_voxel.x; else /* diff.x >= 0 */ box_voxel[l].x = (l & 0x1) ? ds_voxel.x : ds_voxel.x+1; if (diff.y < 0) box_voxel[l].y = (l & 0x2) ? ds_voxel.y-1 : ds_voxel.y; else /* diff.y >= 0 */ box_voxel[l].y = (l & 0x2) ? ds_voxel.y : ds_voxel.y+1; if (diff.z < 0) box_voxel[l].z = (l & 0x4) ? ds_voxel.z-1 : ds_voxel.z; else /* diff.z >= 0 */ box_voxel[l].z = (l & 0x4) ? ds_voxel.z : ds_voxel.z+1; VOXEL_TO_POINT(box_voxel[l], data_set->voxel_size, box_point[l]); /* get the value of the point on the box */ if (amitk_raw_data_includes_voxel(data_set->raw_data, box_voxel[l])) box_value[l] = AMITK_DATA_SET_DOUBLE_0D_SCALING_CONTENT(data_set, box_voxel[l]); else { box_value[l] = NAN; empties = TRUE; } } if (empties) { /* slow algorithm - checking for empties */ /* reset value */ empties = FALSE; /* do the x direction linear interpolation of the sets of two points */ for (l=0;l<8;l=l+2) { max_diff = box_point[l+1].x-box_point[l].x; weight1 = ((max_diff - (ds_point.x - box_point[l].x))/max_diff); weight2 = ((max_diff - (box_point[l+1].x - ds_point.x))/max_diff); if (isnan(box_value[l])) { if (weight2 >= weight1) box_value[l] = box_value[l+1]; /* else box_value[l] left as is (NAN/empty) */ } else if (isnan(box_value[l+1])) { if (weight1 < weight2) box_value[l] = NAN; /* else box_value[l] left as is */ } else box_value[l] = (box_value[l] * weight1) + (box_value[l+1] * weight2); } /* do the y direction linear interpolation of the sets of two points */ for (l=0;l<8;l=l+4) { max_diff = box_point[l+2].y-box_point[l].y; weight1 = ((max_diff - (ds_point.y - box_point[l].y))/max_diff); weight2 = ((max_diff - (box_point[l+2].y - ds_point.y))/max_diff); if (isnan(box_value[l])) { if (weight2 >= weight1) box_value[l] = box_value[l+2]; /* else box_value[l] left as is (NAN/empty) */ } else if (isnan(box_value[l+2])) { if (weight1 < weight2) box_value[l] = NAN; /* else box_value[l] left as is */ } else box_value[l] = (box_value[l] * weight1) + (box_value[l+2] * weight2); } /* do the z direction linear interpolation of the sets of two points */ for (l=0;l<8;l=l+8) { max_diff = box_point[l+4].z-box_point[l].z; weight1 = ((max_diff - (ds_point.z - box_point[l].z))/max_diff); weight2 = ((max_diff - (box_point[l+4].z - ds_point.z))/max_diff); if (isnan(box_value[l])) { if (weight2 >= weight1) box_value[l] = box_value[l+4]; /* else box_value[l] left as is (NAN/empty) */ } else if (isnan(box_value[l+4])) { if (weight1 < weight2) box_value[l] = NAN; /* else box_value[l] left as is */ } else box_value[l] = (box_value[l] * weight1) + (box_value[l+4] * weight2); } /* separate into MPR/MIP/minIP algorithms */ if (data_set->rendering == AMITK_RENDERING_MPR) { /* MPR */ if (!isnan(box_value[0])) { intermediate_data[k] += weight*box_value[0]; weights[k] += weight; } } else { /* MIP or MINIP */ if ((z == 0) && (ds_voxel.t == start_frame) && (i_gate == 0)) intermediate_data[k]=box_value[0]; else if (data_set->rendering == AMITK_RENDERING_MIP) /* MIP */ intermediate_data[k] = MAX(box_value[0], intermediate_data[k]); else /* MINIP */ intermediate_data[k] = MIN(box_value[0], intermediate_data[k]); } } else { /* faster */ /* do the x direction linear interpolation of the sets of two points */ for (l=0;l<8;l=l+2) { max_diff = box_point[l+1].x-box_point[l].x; weight1 = ((max_diff - (ds_point.x - box_point[l].x))/max_diff); weight2 = ((max_diff - (box_point[l+1].x - ds_point.x))/max_diff); box_value[l] = (box_value[l] * weight1) + (box_value[l+1] * weight2); } /* do the y direction linear interpolation of the sets of two points */ for (l=0;l<8;l=l+4) { max_diff = box_point[l+2].y-box_point[l].y; weight1 = ((max_diff - (ds_point.y - box_point[l].y))/max_diff); weight2 = ((max_diff - (box_point[l+2].y - ds_point.y))/max_diff); box_value[l] = (box_value[l] * weight1) + (box_value[l+2] * weight2); } /* do the z direction linear interpolation of the sets of two points */ for (l=0;l<8;l=l+8) { max_diff = box_point[l+4].z-box_point[l].z; weight1 = ((max_diff - (ds_point.z - box_point[l].z))/max_diff); weight2 = ((max_diff - (box_point[l+4].z - ds_point.z))/max_diff); box_value[l] = (box_value[l] * weight1) + (box_value[l+4] * weight2); } /* separate into MPR/MIP/minIP algorithms */ if (data_set->rendering == AMITK_RENDERING_MPR) { /* MPR */ intermediate_data[k] += weight*box_value[0]; weights[k] += weight; } else { /* MIP or MINIP */ if ((z == 0) && (ds_voxel.t == start_frame) && (i_gate == 0)) intermediate_data[k]=box_value[0]; else if (data_set->rendering == AMITK_RENDERING_MIP) /* MIP */ intermediate_data[k] = MAX(intermediate_data[k], box_value[0]); else /* MINIP */ intermediate_data[k] = MIN(intermediate_data[k], box_value[0]); } } /* slow (empties) vs fast algorithm */ slice_point.x += slice->voxel_size.x; } } } } } break; case AMITK_INTERPOLATION_NEAREST_NEIGHBOR: default: /* figure out what point in the data set we're going to start at */ start_point.x = ((amide_real_t) start.x+0.5) * slice->voxel_size.x; start_point.y = ((amide_real_t) start.y+0.5) * slice->voxel_size.y; if (ceil(z_steps) > 1.0) start_point.z = voxel_length/2.0; else start_point.z = slice->voxel_size.z/2.0; /* only one iteration in z */ start_point = amitk_space_s2s(slice_space, data_set_space, start_point); /* figure out what stepping one voxel in a given direction in our slice cooresponds to in our data set */ for (i_axis = 0; i_axis < AMITK_AXIS_NUM; i_axis++) { alt.x = (i_axis == AMITK_AXIS_X) ? slice->voxel_size.x : 0.0; alt.y = (i_axis == AMITK_AXIS_Y) ? slice->voxel_size.y : 0.0; alt.z = (i_axis == AMITK_AXIS_Z) ? voxel_length : 0.0; alt = point_add(point_sub(amitk_space_s2b(slice_space, alt), AMITK_SPACE_OFFSET(slice_space)), AMITK_SPACE_OFFSET(data_set_space)); stride[i_axis] = amitk_space_b2s(data_set_space, alt); } /* iterate over the number of frames we'll be incorporating into this slice */ for (ds_voxel.t = start_frame; ds_voxel.t <= end_frame; ds_voxel.t++) { /* averaging over more then one frame */ if (end_frame-start_frame > 0) { if (ds_voxel.t == start_frame) time_weight = (amitk_data_set_get_end_time(data_set, start_frame)-start_time)/(duration*num_gates); else if (ds_voxel.t == end_frame) time_weight = (end_time-amitk_data_set_get_start_time(data_set, end_frame))/(duration*num_gates); else time_weight = amitk_data_set_get_frame_duration(data_set, ds_voxel.t)/(duration*num_gates); } else time_weight = 1.0/((gdouble) num_gates); /* iterate over gates */ for (i_gate=0; i_gate < num_gates; i_gate++) { if (gate < 0) ds_voxel.g = i_gate+AMITK_DATA_SET_VIEW_START_GATE(data_set); else ds_voxel.g = i_gate+gate; if (ds_voxel.g >= AMITK_DATA_SET_NUM_GATES(data_set)) ds_voxel.g -= AMITK_DATA_SET_NUM_GATES(data_set); ds_point = start_point; /* separate into MPR and MIP/MINIP algorithms. A fair amount of code is duplicated within the algorithms. The reason they aren't combined is to keep the MPR vs MIP/MINIP branch point out of the loop and speed things up slightly for the most commonly used selection (MPR) */ switch(data_set->rendering) { case AMITK_RENDERING_MPR: /* iterate over the number of planes we'll be compressing into this slice */ for (z = 0; z < ceil(z_steps); z++) { last[AMITK_AXIS_Z] = ds_point; /* weight is between 0 and 1, this is used to weight the last voxel in the slice's z direction */ if (floor(z_steps) > z) weight = time_weight/z_steps; else weight = time_weight*(z_steps-floor(z_steps)) / z_steps; /* iterate over x and y */ for (i_voxel.y = start.y, k=0; i_voxel.y <= end.y; i_voxel.y++) { last[AMITK_AXIS_Y] = ds_point; for (i_voxel.x = start.x; i_voxel.x <= end.x; i_voxel.x++, k++) { POINT_TO_VOXEL_COORDS_ONLY(ds_point, data_set->voxel_size, ds_voxel); if (amitk_raw_data_includes_voxel(data_set->raw_data,ds_voxel)) { intermediate_data[k] += weight*AMITK_DATA_SET_DOUBLE_0D_SCALING_CONTENT(data_set,ds_voxel); weights[k] += weight; } POINT_ADD(ds_point, stride[AMITK_AXIS_X], ds_point); } /* x */ POINT_ADD(last[AMITK_AXIS_Y], stride[AMITK_AXIS_Y], ds_point); } /* y */ POINT_ADD(last[AMITK_AXIS_Z], stride[AMITK_AXIS_Z], ds_point); } /* z */ break; case AMITK_RENDERING_MIP: case AMITK_RENDERING_MINIP: /* iterate over the number of planes we'll be compressing into this slice */ for (z = 0; z < ceil(z_steps); z++) { last[AMITK_AXIS_Z] = ds_point; /* need to initialize based on the first plane we encounter */ if ((z == 0) && (ds_voxel.t == start_frame) && (i_gate == 0)) { /* iterate over x and y */ for (i_voxel.y = start.y,k=0; i_voxel.y <= end.y; i_voxel.y++) { last[AMITK_AXIS_Y] = ds_point; for (i_voxel.x = start.x; i_voxel.x <= end.x; i_voxel.x++,k++) { POINT_TO_VOXEL_COORDS_ONLY(ds_point, data_set->voxel_size, ds_voxel); if (!amitk_raw_data_includes_voxel(data_set->raw_data,ds_voxel)) intermediate_data[k] = NAN; else intermediate_data[k] = AMITK_DATA_SET_DOUBLE_0D_SCALING_CONTENT(data_set,ds_voxel); POINT_ADD(ds_point, stride[AMITK_AXIS_X], ds_point); } /* x */ POINT_ADD(last[AMITK_AXIS_Y], stride[AMITK_AXIS_Y], ds_point); } /* y */ } else { /* iterate over everything that's not the first plane */ if (data_set->rendering == AMITK_RENDERING_MIP) { /* iterate over x and y */ for (i_voxel.y = start.y,k=0; i_voxel.y <= end.y; i_voxel.y++) { last[AMITK_AXIS_Y] = ds_point; for (i_voxel.x = start.x; i_voxel.x <= end.x; i_voxel.x++,k++) { POINT_TO_VOXEL_COORDS_ONLY(ds_point, data_set->voxel_size, ds_voxel); if (amitk_raw_data_includes_voxel(data_set->raw_data,ds_voxel)) intermediate_data[k] = MAX(intermediate_data[k], AMITK_DATA_SET_DOUBLE_0D_SCALING_CONTENT(data_set,ds_voxel)); POINT_ADD(ds_point, stride[AMITK_AXIS_X], ds_point); } /* x */ POINT_ADD(last[AMITK_AXIS_Y], stride[AMITK_AXIS_Y], ds_point); } /* y */ } else { /* AMITK_RENDERING_MINIP */ /* iterate over x and y */ for (i_voxel.y = start.y,k=0; i_voxel.y <= end.y; i_voxel.y++) { last[AMITK_AXIS_Y] = ds_point; for (i_voxel.x = start.x; i_voxel.x <= end.x; i_voxel.x++,k++) { POINT_TO_VOXEL_COORDS_ONLY(ds_point, data_set->voxel_size, ds_voxel); if (amitk_raw_data_includes_voxel(data_set->raw_data,ds_voxel)) intermediate_data[k] = MIN(intermediate_data[k], AMITK_DATA_SET_DOUBLE_0D_SCALING_CONTENT(data_set,ds_voxel)); POINT_ADD(ds_point, stride[AMITK_AXIS_X], ds_point); } /* x */ POINT_ADD(last[AMITK_AXIS_Y], stride[AMITK_AXIS_Y], ds_point); } /* y */ } /* end else, MIP vs MINIP */ } /* end else */ POINT_ADD(last[AMITK_AXIS_Z], stride[AMITK_AXIS_Z], ds_point); } /* z */ break; default: break; } /* MIP vs NON-MIP */ } /* iterating over gates */ } /* iterating over frames */ break; } /* fill in data/normalize if needed */ i_voxel.t = i_voxel.g = i_voxel.z = 0; if (data_set->rendering == AMITK_RENDERING_MPR) { for (i_voxel.y = start.y,k=0; i_voxel.y <= end.y; i_voxel.y++) for (i_voxel.x = start.x; i_voxel.x <= end.x; i_voxel.x++,k++) if (weights[k] > 0) AMITK_RAW_DATA_DOUBLE_SET_CONTENT(slice->raw_data,i_voxel) = intermediate_data[k]/weights[k]; else AMITK_RAW_DATA_DOUBLE_SET_CONTENT(slice->raw_data,i_voxel) = NAN; } else { /* MIP or MINIP */ for (i_voxel.y = start.y,k=0; i_voxel.y <= end.y; i_voxel.y++) for (i_voxel.x = start.x; i_voxel.x <= end.x; i_voxel.x++,k++) AMITK_RAW_DATA_DOUBLE_SET_CONTENT(slice->raw_data,i_voxel) = intermediate_data[k]; } error: if (weights != NULL) g_free(weights); if (intermediate_data != NULL) g_free(intermediate_data); return slice; }