// 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 }