void SegmentationWindow::OnUpdateMenuSegmentationSplitNodeAddSubgroup(wxUpdateUIEvent& e)
{
	e.Enable(false);

	// Check that the selection is available.
	if(!m_model->selection()) return;

	// Check that we're in the process of splitting a node.
	PartitionView::NodeSplitManager_Ptr nodeSplitManager = m_view->node_split_manager();
	PFNodeID splitNode = nodeSplitManager->split_node();
	if(splitNode == PFNodeID::invalid()) return;

	// Check that we're viewing the layer containing the split children, and that all the selected nodes are in this layer.
	int viewLayer = m_view->camera()->slice_location().layer;
	if(viewLayer != splitNode.layer() - 1) return;

	int mergeLayer = m_model->selection()->merge_layer(viewLayer);
	if(mergeLayer != viewLayer) return;

	// Check that all the selected nodes are as-yet-unallocated children of the split node.
	std::set<PFNodeID> selectedNodes(m_model->selection()->view_at_layer_cbegin(mergeLayer), m_model->selection()->view_at_layer_cend(mergeLayer));
	const std::set<PFNodeID>& unallocatedChildren = nodeSplitManager->unallocated_children();
	if(!std::includes(unallocatedChildren.begin(), unallocatedChildren.end(), selectedNodes.begin(), selectedNodes.end())) return;

	// Check that the selected nodes are connected.
	std::set<int> selectedNodeIndices;
	for(std::set<PFNodeID>::const_iterator it=selectedNodes.begin(), iend=selectedNodes.end(); it!=iend; ++it)
	{
		selectedNodeIndices.insert(it->index());
	}
	e.Enable(m_model->volume_ipf()->are_connected(selectedNodeIndices, splitNode.layer() - 1));
}
void SegmentationWindow::OnUpdateSingleNonLowestNodeSelectionNeeder(wxUpdateUIEvent& e)
{
	e.Enable(false);
	if(m_model->selection())
	{
		int layerIndex = m_view->camera()->slice_location().layer;
		if(layerIndex > 1)
		{
			int nodeCount = std::distance(m_model->selection()->view_at_layer_cbegin(layerIndex), m_model->selection()->view_at_layer_cend(layerIndex));
			if(nodeCount == 1)
			{
				PFNodeID node = *m_model->selection()->view_at_layer_cbegin(layerIndex);
				e.Enable(node.layer() == layerIndex);
			}
		}
	}
}
void SegmentationWindow::OnUpdateMenuSegmentationSplitNodeRemoveSubgroup(wxUpdateUIEvent& e)
{
	e.Enable(false);

	// Check that the node split manager is available.
	PartitionView::NodeSplitManager_Ptr nodeSplitManager = m_view->node_split_manager();
	if(!nodeSplitManager) return;

	// Check that only one node is selected (when viewed from the current layer).
	int layerIndex = m_view->camera()->slice_location().layer;
	int nodeCount = std::distance(m_model->selection()->view_at_layer_cbegin(layerIndex), m_model->selection()->view_at_layer_cend(layerIndex));
	if(nodeCount != 1) return;

	// Check the node is actually in the layer being viewed.
	PFNodeID node = *m_model->selection()->view_at_layer_cbegin(layerIndex);
	if(node.layer() != layerIndex) return;

	// Check that the node is an allocated child of the node currently being split.
	const std::set<PFNodeID>& allocatedChildren = nodeSplitManager->allocated_children();
	e.Enable(allocatedChildren.find(node) != allocatedChildren.end());
}
bool SpleenIdentifier3D::is_candidate(const PFNodeID& node, const BranchProperties& properties) const
{
	itk::Index<3> volumeSize = ITKImageUtil::make_index_from_size(dicom_volume()->size());
	int sliceCount = properties.z_max() + 1 - properties.z_min();
	int minVoxelsPerSlice = 1000;
	int maxVoxelsPerSlice = 7000;

	return	node.layer() == 1 &&															// it must be in the lowest branch layer
			140 <= properties.mean_grey_value() && properties.mean_grey_value() <= 170 &&	// it must have a reasonable grey value
			properties.x_max() >= volumeSize[0]*0.8 &&										// it must stretch sufficiently far to the right
			properties.voxel_count() >= minVoxelsPerSlice * sliceCount &&					// it must be of a reasonable size
			properties.voxel_count() <= maxVoxelsPerSlice * sliceCount;
}