diff --git a/src/Region/RegionHandler.cc b/src/Region/RegionHandler.cc index d7de24111..8347bbfb3 100644 --- a/src/Region/RegionHandler.cc +++ b/src/Region/RegionHandler.cc @@ -1931,6 +1931,54 @@ bool RegionHandler::GetRegionHistogramData( return true; } +// ***** Fill 3d rendering ***** +// GeneratorProgressCallback progress_callback, CARTA::Render3DData& render3d_data + + +bool RegionHandler::SendRender3DData(int file_id, int region_id, int viewer_id, + AxisRange& spectral_range, int rebin_xy, int rebin_z, std::shared_ptr& frame, CARTA::Render3DResponse& render3d_response) { + + RegionState region_state = _regions.at(region_id)->GetRegionState(); + + auto stokes = frame->CurrentStokes(); + PreviewCubeParameters cube_parameters(file_id, region_id, spectral_range, rebin_xy, rebin_z, stokes, region_state); + + auto frame_id = GetRender3DViewerFrameId(viewer_id); + bool viewer_frame_set = _frames.find(frame_id) != _frames.end(); + + // Update cube settings for existing ID. + // Set unique locks so in-progress cubes are completed before update. + std::unique_lock render3d_cube_lock(_render3d_cube_mutex); + if (_render3d_cubes.find(viewer_id) == _render3d_cubes.end() || + !_render3d_cubes.at(viewer_id)->HasSameParameters(cube_parameters)) { + // Cube changed, see if set for another viewer ID + bool cube_found(false); + for (auto& render3d_cube : _render3d_cubes) { + if (render3d_cube.second->HasSameParameters(cube_parameters)) { + _render3d_cubes[viewer_id] = render3d_cube.second; + cube_found = true; + break; + } + } + if (!cube_found) { + _render3d_cubes[viewer_id] = std::shared_ptr(new PvPreviewCube(cube_parameters)); + } + + // If preview cube changed, then frame for its preview image cube is invalid + viewer_frame_set = false; + } + auto render3d_cube = _render3d_cubes.at(viewer_id); + bool render3d_cube_loaded = render3d_cube->CubeLoaded(); + render3d_cube_lock.unlock(); + + +} + +bool RegionHandler::FillRender3DData(std::function cb) { + + +} + // ***** Fill spectral profile ***** bool RegionHandler::FillSpectralProfileData( diff --git a/src/Region/RegionHandler.h b/src/Region/RegionHandler.h index 6236fbf5b..9d4ee1465 100644 --- a/src/Region/RegionHandler.h +++ b/src/Region/RegionHandler.h @@ -65,6 +65,7 @@ class RegionHandler { bool FillRegionStatsData(std::function cb, int region_id, int file_id); bool FillPointSpatialProfileData(int file_id, int region_id, std::vector& spatial_data_vec); bool FillLineSpatialProfileData(int file_id, int region_id, std::function cb); + bool FillRender3DData(); // Calculate moments bool CalculateMoments(int file_id, int region_id, const std::shared_ptr& frame, GeneratorProgressCallback progress_callback, diff --git a/src/Session/Session.cc b/src/Session/Session.cc index c6941c6a5..49935f31c 100644 --- a/src/Session/Session.cc +++ b/src/Session/Session.cc @@ -1338,12 +1338,63 @@ bool Session::OnConcatStokesFiles(const CARTA::ConcatStokesFiles& message, uint3 } void Session::OnRender3DRequest(const CARTA::Render3DRequest& render3d_request, uint32_t request_id) { + // return true if data sent + bool data_sent(false); + + // Unpack request message int file_id(render3d_request.file_id()); int region_id(render3d_request.region_id()); int viewer_id(render3d_request.viewer_id()); + bool keep(render3d_request.keep()); + AxisRange spectral_range; + if (render3d_request.has_spectral_range()) { + spectral_range = AxisRange(render3d_request.spectral_range().min(), render3d_request.spectral_range().max()); + } else { + spectral_range = AxisRange(0, frame->Depth() - 1); + } + int rebin_xy = std::max(render3d_request.rebin_xy(), 1); + int rebin_z = std::max(render3d_request.rebin_z(), 1); + auto compression = render3d_request.compression_type(); + float image_quality = render3d_request.image_compression_quality(); + CARTA::Render3DResponse render3d_response; std::cout << "Render3D function called" << std::endl; + // Checks for valid request: + // 1. Region is set. For Render3D Region is optional + // if (!RegionSet(region_id, true)) { + // render3d_response.set_message("3D Rendering requested for invalid region."); + // return false; + // } + bool is_image_region(region_id == IMAGE_REGION_ID); + if (!is_image_region) { + if (!RegionSet(region_id)) { + render3d_response.set_message("3D rendering cube requested for invalid region id."); + return false; + } + if (!IsClosedRegion(region_id)) { + render3d_response.set_message("3D rendering cube requested for invalid region type."); + return false; + } + + // 2. Region is closed + if (!IsClosedRegion(region_id)) { + render3d_response.set_message("Region type not supported for 3D Rendering."); + return false; + } + + // 3. Image has spectral axis + if (!frame->CoordinateSystem()->hasSpectralAxis()) { + render3d_response.set_message("No spectral coordinate for generating 3D rendering."); + return false; + } + + // 4. Image is smaller than limit + if (frame->Width() * frame->Height() * frame->Depth() > MAX_RENDER3D_PIXELS) { + render3d_response.set_message("Cube size exceeds maximum for 3D Rendering. Please use smaller region or spectral range."); + return false; + } + if (_frames.count(file_id)) { // condition statement to check if the a region is selected. cursor_region is 0 and NONE, IMAGE and ACTIVE are < 0 // if (!_region_handler || (region_id <= CURSOR_REGION_ID)) { @@ -1354,16 +1405,32 @@ void Session::OnRender3DRequest(const CARTA::Render3DRequest& render3d_request, auto& frame = _frames.at(file_id); CARTA::Render3DData render3d_data; + data_sent = _region_handler->SendRender3DData( + [&](CARTA::Render3DData& render3d_data) { + // send (partial) render3d datacube to frontend + SendEvent(CARTA::EventType::RENDER3D_DATA, request_id, render3d_data); + }, + ) + // Set render3d progress callback function - auto progress_callback = [&](float progress) { - auto render3d_progress = Message::Render3DProgress(file_id, region_id, progress, viewer_id); - SendEvent(CARTA::EventType::RENDER3D_PROGRESS, request_id, render3d_progress); - }; + // auto progress_callback = [&](float progress) { + // auto render3d_progress = Message::Render3DProgress(file_id, region_id, progress, viewer_id); + // SendEvent(CARTA::EventType::RENDER3D_PROGRESS, request_id, render3d_progress); + // }; - if (_region_handler->CalculateRender3DData(render3d_request, frame, progress_callback, render3d_response, render3d_data)) { + // if (_region_handler->CalculateRender3DData(render3d_request, frame, progress_callback, render3d_response, render3d_data)) { - } + // } + + } + // check if data was sent and send response accordingly + if (data_sent) { + render3d_response.set_success(true); + } else { + render3d_response.set_success(false); + render3d_response.set_message("3D data not sent."); } + SendEvent(CARTA::EventType::RENDER3D_RESPONSE, request_id, render3d_response); } void Session::OnPvRequest(const CARTA::PvRequest& pv_request, uint32_t request_id) {