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) {