// The 'computeSliceSpacing' method
double LoadSeriesThread::computeSliceSpacing(OrthancClient::Series& series) const
{
    OrthancClient::Instance instance = series.GetInstance(0);
    instance.LoadTagContent("0020-0032"); // ImagePositionPatient
    QString pos1 = instance.GetLoadedTagContent().c_str();
    QStringList pos1s = pos1.split("\\");
    Vector3D pos1vector(pos1s.at(0).toDouble(), pos1s.at(1).toDouble(),
                        pos1s.at(2).toDouble());

    instance.LoadTagContent("0020-0037"); // ImageOrientationPatient
    QString or1 = instance.GetLoadedTagContent().c_str();
    QStringList or1s = or1.split("\\");
    Vector3D v(or1s.at(0).toDouble(), or1s.at(1).toDouble(), or1s.at(2).toDouble());
    Vector3D w(or1s.at(3).toDouble(), or1s.at(4).toDouble(), or1s.at(5).toDouble());

    Vector3D n = v.crossProduct(w);
    n.normalize();

    double min = -1;
    for(unsigned int i = 1 ; i < series.GetInstanceCount() ; i++) // TODO normally one can be enough but some bug forced me to search for the minest
    {
        OrthancClient::Instance instance2 = series.GetInstance(i);
        instance2.LoadTagContent("0020-0032");
        QString pos2 = instance2.GetLoadedTagContent().c_str();
        QStringList pos2s = pos2.split("\\");
        Vector3D pos2vector(pos2s.at(0).toDouble(), pos2s.at(1).toDouble(),
                            pos2s.at(2).toDouble());

        double dist = fabs(n.dotProduct(pos1vector-pos2vector));
        if(dist < min || min < 0)
            min = dist;
    }

    return min;
}
예제 #2
0
void Display(OrthancClient::Series& series)
{
  /**
   * Load the 3D image from Orthanc into VTK.
   **/

  vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();
  image->SetDimensions(series.GetWidth(), series.GetHeight(), series.GetInstanceCount());
  image->SetScalarType(VTK_SHORT);
  image->AllocateScalars();

  if (series.GetWidth() != 0 &&
      series.GetHeight() != 0 && 
      series.GetInstanceCount() != 0)
  {
    DisplayProgress listener;
    series.Load3DImage(image->GetScalarPointer(0, 0, 0), Orthanc::PixelFormat_SignedGrayscale16,
                       2 * series.GetWidth(), 2 * series.GetHeight() * series.GetWidth(), listener);
  }

  float sx, sy, sz;
  series.GetVoxelSize(sx, sy, sz);
  image->SetSpacing(sx, sy, sz);


  /**
   * The following code is based on the VTK sample for MIP
   * http://www.vtk.org/Wiki/VTK/Examples/Cxx/VolumeRendering/MinIntensityRendering
   **/

  // Create a transfer function mapping scalar value to opacity
  double range[2];
  image->GetScalarRange(range);

  vtkSmartPointer<vtkPiecewiseFunction> opacityTransfer = 
    vtkSmartPointer<vtkPiecewiseFunction>::New();
  opacityTransfer->AddSegment(range[0], 0.0, range[1], 1.0);
 
  vtkSmartPointer<vtkColorTransferFunction> colorTransfer = 
    vtkSmartPointer<vtkColorTransferFunction>::New();
  colorTransfer->AddRGBPoint(0, 1.0, 1.0, 1.0);
  colorTransfer->AddRGBPoint(range[1], 1.0, 1.0, 1.0);
 
  vtkSmartPointer<vtkVolumeProperty> property = 
    vtkSmartPointer<vtkVolumeProperty>::New();
  property->SetScalarOpacity(opacityTransfer);
  property->SetColor(colorTransfer);
  property->SetInterpolationTypeToLinear();

  // Create a Maximum Intensity Projection rendering
  vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> mapper = 
    vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
  mapper->SetBlendModeToMaximumIntensity();
  mapper->SetInput(image);

  vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
  volume->SetMapper(mapper);
  volume->SetProperty(property);
  
  vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkOpenGLRenderer>::New();
  renderer->AddViewProp(volume);
  renderer->SetBackground(0.1, 0.2, 0.3); // Background color dark blue

  vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = 
    vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
 
  vtkSmartPointer<vtkRenderWindow> window = vtkSmartPointer<vtkRenderWindow>::New();
  window->AddRenderer(renderer); 

  vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  interactor->SetRenderWindow(window);
  interactor->SetInteractorStyle(style);
  interactor->Start();
}