// GetGoogleSpec returns a google-specific tile spec, which includes how the tile 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) GetGoogleSpec(scaling Scaling, plane dvid.DataShape, offset dvid.Point3d, size dvid.Point2d) (*GoogleTileSpec, error) { tile := new(GoogleTileSpec) tile.offset = offset // Convert combination of plane and size into 3d size. sizeWant, err := dvid.GetPoint3dFrom2d(plane, size, 1) if err != nil { return nil, err } tile.sizeWant = sizeWant // Determine which geometry is appropriate given the scaling and the shape/orientation tileSpec, err := GetTileSpec(scaling, plane) if err != nil { return nil, err } geomIndex, found := d.TileMap[*tileSpec] if !found { return nil, fmt.Errorf("Could not find scaled volume in %q for %s with scaling %d", d.DataName(), plane, scaling) } geom := d.Scales[geomIndex] tile.gi = geomIndex tile.channelCount = geom.ChannelCount tile.channelType = geom.ChannelType // Get the # bytes for each pixel switch geom.ChannelType { case "uint8": tile.bytesPerVoxel = 1 case "float": tile.bytesPerVoxel = 4 case "uint64": tile.bytesPerVoxel = 8 default: return nil, fmt.Errorf("Unknown volume channel type in %s: %s", d.DataName(), geom.ChannelType) } // Check if the tile is completely outside the volume. volumeSize := geom.VolumeSize if offset[0] >= volumeSize[0] || offset[1] >= volumeSize[1] || offset[2] >= volumeSize[2] { tile.outside = true return tile, nil } // Check if the tile is on the edge and adjust size. var adjSize dvid.Point3d = sizeWant maxpt, err := offset.Expand2d(plane, size) for i := 0; i < 3; i++ { if maxpt[i] > volumeSize[i] { tile.edge = true adjSize[i] = volumeSize[i] - offset[i] } } tile.size = adjSize return tile, nil }
// 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 }