// GetGoogleSubvolGeom returns a google-specific voxel spec, which includes how the data is positioned relative to // scaled volume boundaries. Not that the size parameter is the desired size and not what is required to fit // within a scaled volume. func (d *Data) GetGoogleSubvolGeom(scaling Scaling, shape dvid.DataShape, offset dvid.Point3d, size dvid.Point) (*GoogleSubvolGeom, error) { gsg := new(GoogleSubvolGeom) if err := gsg.shape.FromShape(shape); err != nil { return nil, err } gsg.offset = offset // If 2d plane, convert combination of plane and size into 3d size. if size.NumDims() == 2 { size2d := size.(dvid.Point2d) sizeWant, err := dvid.GetPoint3dFrom2d(shape, size2d, 1) if err != nil { return nil, err } gsg.sizeWant = sizeWant } else { var ok bool gsg.sizeWant, ok = size.(dvid.Point3d) if !ok { return nil, fmt.Errorf("Can't convert %v to dvid.Point3d", size) } } // Determine which geometry is appropriate given the scaling and the shape/orientation tileSpec, err := GetGSpec(scaling, shape) if err != nil { return nil, err } geomIndex, found := d.GeomMap[*tileSpec] if !found { return nil, fmt.Errorf("Could not find scaled volume in %q for %s with scaling %d", d.DataName(), shape, scaling) } geom := d.Scales[geomIndex] gsg.gi = geomIndex gsg.channelCount = geom.ChannelCount gsg.channelType = geom.ChannelType // Get the # bytes for each pixel switch geom.ChannelType { case "UINT8": gsg.bytesPerVoxel = 1 case "FLOAT": gsg.bytesPerVoxel = 4 case "UINT64": gsg.bytesPerVoxel = 8 default: return nil, fmt.Errorf("Unknown volume channel type in %s: %s", d.DataName(), geom.ChannelType) } // Check if the requested area is completely outside the volume. volumeSize := geom.VolumeSize if offset[0] >= volumeSize[0] || offset[1] >= volumeSize[1] || offset[2] >= volumeSize[2] { gsg.outside = true return gsg, nil } // Check if the requested shape is on the edge and adjust size. adjSize := gsg.sizeWant maxpt := offset.Add(adjSize) for i := uint8(0); i < 3; i++ { if maxpt.Value(i) > volumeSize[i] { gsg.edge = true adjSize[i] = volumeSize[i] - offset[i] } } gsg.size = adjSize return gsg, nil }