<commit_before>/*=========================================================================

  Program: Bender

  Copyright (c) Kitware Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=========================================================================*/

// Bender includes
#include "CreateTetrahedralMeshCLP.h"
#include "benderIOUtils.h"
#include "vtkBrokenCells.h"

// ITK includes
#include "itkBinaryThresholdImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkImageFileWriter.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIterator.h"
#include "itkRelabelComponentImageFilter.h"
#include "itkConstantPadImageFilter.h"

// Slicer includes
#include "itkPluginUtilities.h"

// VTK includes
#include <vtkCleanPolyData.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkTetra.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkPolyData.h>
#include <vtkPolyDataWriter.h>
#include <vtkMath.h>
#include <vtkNew.h>
#include <vtkSmartPointer.h>

// Cleaver includes
#include <Cleaver/Cleaver.h>
#include <Cleaver/InverseField.h>
#include <Cleaver/PaddedVolume.h>
#include <Cleaver/ScalarField.h>
#include <Cleaver/Volume.h>
#include <LabelMapField.h>

// Use an anonymous namespace to keep class types and function names
// from colliding when module is used as shared object module.  Every
// thing should be in an anonymous namespace except for the module
// entry point, e.g. main()
//
namespace
{
template <class T> int DoIt( int argc, char * argv[] );

std::vector<Cleaver::LabelMapField::ImageType::Pointer> SplitLabelMaps(
  int    argc,
  char * argv[]);
} // end of anonymous namespace

int main( int argc, char * argv[] )
{

  PARSE_ARGS;

  itk::ImageIOBase::IOPixelType     pixelType;
  itk::ImageIOBase::IOComponentType componentType;

  try
    {
    itk::GetImageType(InputVolume, pixelType, componentType);

    switch( componentType )
      {
    case itk::ImageIOBase::UCHAR:
      return DoIt<unsigned char>( argc, argv );
      break;
    case itk::ImageIOBase::CHAR:
      return DoIt<char>( argc, argv );
      break;
    case itk::ImageIOBase::USHORT:
      return DoIt<unsigned short>( argc, argv );
      break;
    case itk::ImageIOBase::SHORT:
      return DoIt<short>( argc, argv );
      break;
    case itk::ImageIOBase::UINT:
      return DoIt<unsigned int>( argc, argv );
      break;
    case itk::ImageIOBase::INT:
      return DoIt<int>( argc, argv );
      break;
    case itk::ImageIOBase::ULONG:
      return DoIt<unsigned long>( argc, argv );
      break;
    case itk::ImageIOBase::LONG:
      return DoIt<long>( argc, argv );
      break;
    case itk::ImageIOBase::FLOAT:
      return DoIt<float>( argc, argv );
      break;
    case itk::ImageIOBase::DOUBLE:
      return DoIt<double>( argc, argv );
      break;
    case itk::ImageIOBase::UNKNOWNCOMPONENTTYPE:
    default:
      std::cerr << "Unknown component type: " << componentType << std::endl;
      break;
      }
    }

  catch( itk::ExceptionObject & excep )
    {
    std::cerr << argv[0] << ": exception caught !" << std::endl;
    std::cerr << excep << std::endl;
    return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}

// Use an anonymous namespace to keep class types and function names
// from colliding when module is used as shared object module.  Every
// thing should be in an anonymous namespace except for the module
// entry point, e.g. main()
//
namespace
{
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
std::vector<Cleaver::LabelMapField::ImageType::Pointer >
SplitLabelMaps(Cleaver::LabelMapField::ImageType *image, bool verbose)
{

  typedef Cleaver::LabelMapField::ImageType LabelImageType;
  typedef itk::RelabelComponentImageFilter<LabelImageType,
                                           LabelImageType> RelabelFilterType;
  typedef itk::BinaryThresholdImageFilter<LabelImageType,
                                          LabelImageType> ThresholdFilterType;
  typedef itk::ImageFileWriter<LabelImageType> ImageWriterType;

  // Assign continuous labels to the connected components, background is
  // considered to be 0 and will be ignored in the relabeling process.
  RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
  relabelFilter->SetInput( image );
  relabelFilter->Update();

  if (verbose)
    {
    std::cout << "Total Number of Labels: " <<
      relabelFilter->GetNumberOfObjects() << std::endl;
    }

  // Extract the labels
  typedef RelabelFilterType::LabelType LabelType;
  ThresholdFilterType::Pointer skinThresholdFilter =
    ThresholdFilterType::New();

  // Create a list of images corresponding to labels
  std::vector<LabelImageType::Pointer> labels;

  // The skin label will become background for internal (smaller) organs
  skinThresholdFilter->SetInput(relabelFilter->GetOutput());
  skinThresholdFilter->SetLowerThreshold(1);
  skinThresholdFilter->SetUpperThreshold(relabelFilter->GetNumberOfObjects()+1);
  skinThresholdFilter->SetInsideValue(-1);
  skinThresholdFilter->SetOutsideValue(0);
  skinThresholdFilter->Update();
  labels.push_back(skinThresholdFilter->GetOutput());

  for (LabelType i = 1, end = relabelFilter->GetNumberOfObjects()+1; i < end;
       ++i)
    {
    ThresholdFilterType::Pointer organThresholdFilter =
      ThresholdFilterType::New();
    organThresholdFilter->SetInput(relabelFilter->GetOutput());
    organThresholdFilter->SetLowerThreshold(i);
    organThresholdFilter->SetUpperThreshold(i);
    organThresholdFilter->SetInsideValue(i);
    organThresholdFilter->SetOutsideValue(-1);
    organThresholdFilter->Update();

    labels.push_back(organThresholdFilter->GetOutput());
    }

  return labels;
}

//----------------------------------------------------------------------------
bool IsPointInvalid(Cleaver::vec3 pos)
{
  return vtkBrokenCells::IsPointValid(pos.x, pos.y, pos.z);
}

//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
template <class T>
int DoIt( int argc, char * argv[] )
{

  PARSE_ARGS;

  typedef Cleaver::LabelMapField::ImageType LabelImageType;
  typedef T InputPixelType;
  typedef itk::Image<InputPixelType,3> InputImageType;
  typedef itk::CastImageFilter<InputImageType,
                               LabelImageType> CastFilterType;
  typedef itk::ImageFileReader<InputImageType> ReaderType;
  typedef itk::ConstantPadImageFilter<InputImageType,
                                      InputImageType> ConstantPadType;

  typename ReaderType::Pointer reader            = ReaderType::New();
  reader->SetFileName( InputVolume );
  reader->Update();

  typename CastFilterType::Pointer castingFilter = CastFilterType::New();
  castingFilter->SetInput(reader->GetOutput());

  std::vector<Cleaver::ScalarField*> labelMaps;

  std::vector<LabelImageType::Pointer> labels =
    SplitLabelMaps(castingFilter->GetOutput(), Verbose);

  // Get a map from the original labels to the new labels
  std::map<InputPixelType, InputPixelType> originalLabels;

  for(size_t i = 0; i < labels.size(); ++i)
    {
    itk::ImageRegionConstIterator<InputImageType> imageIterator(
      reader->GetOutput(), reader->GetOutput()->GetLargestPossibleRegion());
    itk::ImageRegionConstIterator<LabelImageType> labelsIterator(
      labels[i], labels[i]->GetLargestPossibleRegion());
    bool foundCorrespondence = false;
    while(!imageIterator.IsAtEnd()
      && !labelsIterator.IsAtEnd()
      && !foundCorrespondence)
      {
      if (labelsIterator.Value() > 0)
        {
        originalLabels[labelsIterator.Value()] = imageIterator.Value();
        }

      ++imageIterator;
      ++labelsIterator;
      }
    }

  if (Verbose)
    {
    std::cout << "Total labels found:  " << labels.size() << std::endl;
    }
  for(size_t i = 0; i < labels.size(); ++i)
    {
    labelMaps.push_back(new Cleaver::LabelMapField(labels[i]));
    static_cast<Cleaver::LabelMapField*>(labelMaps.back())->
      SetGenerateDataFromLabels(true);
    }

  if(labelMaps.empty())
    {
    std::cerr << "Failed to load image data. Terminating." << std::endl;
    return 0;
    }
  if(labelMaps.size() < 2)
    {
    labelMaps.push_back(new Cleaver::InverseField(labelMaps[0]));
    }

  Cleaver::AbstractVolume *volume = new Cleaver::Volume(labelMaps);
  if (Padding)
    {
    volume = new Cleaver::PaddedVolume(volume);
    }

  if (Verbose)
    {
    std::cout << "Creating Mesh with Volume Size "
      << volume->size().toString() << std::endl;
    }

  //--------------------------------
  //  Create Mesher & TetMesh
  //--------------------------------
  Cleaver::TetMesh *cleaverMesh =
    Cleaver::createMeshFromVolume(volume, Verbose);
  if (!cleaverMesh)
    {
    // Clean up
    delete volume;
    delete cleaverMesh;

    std::cerr << "Mesh computation failed !" << std::endl;
    return EXIT_FAILURE;
    }

  //------------------
  //  Compute Angles
  //------------------
  if(Verbose)
    {
    cleaverMesh->computeAngles();
    std::cout.precision(12);
    std::cout << "Worst Angles:" << std::endl;
    std::cout << "min: " << cleaverMesh->min_angle << std::endl;
    std::cout << "max: " << cleaverMesh->max_angle << std::endl;
    }

  //-----------------------
  //  Fill polydata arrays
  //-----------------------
  // Constants for undesired material
  const int airLabel = 0;
  int paddedVolumeLabel = labels.size();

  // Points and cell arrays
  vtkNew<vtkCellArray> meshTetras;
  vtkNew<vtkPoints> points;
  points->SetNumberOfPoints(cleaverMesh->tets.size() * 4);

  vtkNew<vtkIntArray> cellData;
  cellData->SetName("Labels");

  vtkNew<vtkBrokenCells> brokenCells;
  brokenCells->SetPoints(points.GetPointer());
  brokenCells->SetVerbose(Verbose);
  for(size_t i = 0; i < cleaverMesh->tets.size(); ++i)
    {
    int label = cleaverMesh->tets[i]->mat_label;

    if(label == airLabel || label == paddedVolumeLabel)
      {
      continue;
      }

    vtkNew<vtkTetra> meshTetra;
    for (int j = 0; j < 4; ++j)
      {
      Cleaver::vec3 &pos = cleaverMesh->tets[i]->verts[j]->pos();
      int vertexIndex = cleaverMesh->tets[i]->verts[j]->tm_v_index;

      points->SetPoint(vertexIndex, pos.x, pos.y, pos.z);
      meshTetra->GetPointIds()->SetId(j, vertexIndex);

      // If invalid, flag the cell so it can be rebuild later
      if (! IsPointInvalid(pos))
        {
        std::cerr << "Invalid point for cell " << i
          << ", this point will be patched up but something went wrong with"
          << " Cleaver !" << std::endl;
        brokenCells->AddCell(vertexIndex, meshTetra.GetPointer());
        }
      }

    meshTetras->InsertNextCell(meshTetra.GetPointer());
    cellData->InsertNextValue(originalLabels[label]);
    }

  //  Repair broken cells
  if (! brokenCells->RepairAllCells())
    {
    delete volume;
    delete cleaverMesh;
    return EXIT_FAILURE;
    }

  //-----------------------------
  //  Create and clean polydata
  //-----------------------------

  vtkSmartPointer<vtkPolyData> vtkMesh = vtkSmartPointer<vtkPolyData>::New();
  vtkMesh->SetPoints(points.GetPointer());
  vtkMesh->SetPolys(meshTetras.GetPointer());
  vtkMesh->GetCellData()->SetScalars(cellData.GetPointer());

  vtkNew<vtkCleanPolyData> cleanFilter;
  cleanFilter->PointMergingOff(); // Prevent from creating triangles or lines
  cleanFilter->SetInput(vtkMesh);

  //---------------------------------------
  //  Transform polydata to fit the image
  //---------------------------------------
  // Since cleaver does not take into account the image properties such as
  // spacing or origin, we need to transform the output points so the mesh can
  // match the original image.
  vtkNew<vtkTransform> transform;
  LabelImageType::SpacingType spacing = reader->GetOutput()->GetSpacing();
  LabelImageType::PointType origin = reader->GetOutput()->GetOrigin();
  LabelImageType::DirectionType imageDirection =
    reader->GetOutput()->GetDirection();

  // Transform points to RAS (what is concatenated first is done last !)
  vtkNew<vtkMatrix4x4> rasMatrix;
  rasMatrix->Identity();
  rasMatrix->SetElement(0, 0, -1.0);
  rasMatrix->SetElement(1, 1, -1.0);
  transform->Concatenate(rasMatrix.GetPointer());

  // Translation
  double voxelSize[3];
  voxelSize[0] = spacing[0]; voxelSize[1] = spacing[1]; voxelSize[2] = spacing[2];
  double voxelDiagonale = vtkMath::Norm(voxelSize) / 2;

  vtkNew<vtkMatrix4x4> directionMatrix;
  directionMatrix->Identity();
  for (int i = 0; i < imageDirection.RowDimensions; ++i)
    {
    for (int j = 0; j < imageDirection.ColumnDimensions; ++j)
      {
      directionMatrix->SetElement(i, j, imageDirection[i][j]);
      }
    }

  vtkNew<vtkTransform> offsetTransform;
  offsetTransform->Concatenate(directionMatrix.GetPointer());
  double offset =
    Padding ? (Cleaver::PaddedVolume::DefaultThickness + 1) * voxelDiagonale : 0.;
  double* offsets =
    offsetTransform->TransformDoubleVector(offset, offset, offset);
  transform->Translate(
    origin[0] - offsets[0],
    origin[1] - offsets[1],
    origin[2] - offsets[2]);

  // Scaling and rotation
  vtkNew<vtkMatrix4x4> scaleMatrix;
  scaleMatrix->DeepCopy(directionMatrix.GetPointer());
  for (int i = 0; i < spacing.GetNumberOfComponents(); ++i)
    {
    scaleMatrix->SetElement(i, i, scaleMatrix->GetElement(i, i) * spacing[i]);
    }
  transform->Concatenate(scaleMatrix.GetPointer());

  // Actual transformation
  vtkNew<vtkTransformPolyDataFilter> transformFilter;
  transformFilter->SetInput(cleanFilter->GetOutput());
  transformFilter->SetTransform(transform.GetPointer());

  bender::IOUtils::WritePolyData(transformFilter->GetOutput(), OutputMesh);

  // Clean up
  delete volume;
  delete cleaverMesh;

  return EXIT_SUCCESS;
}

} // end of anonymous namespace

<commit_msg>Fix not-padded mesh transformations<commit_after>/*=========================================================================

  Program: Bender

  Copyright (c) Kitware Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=========================================================================*/

// Bender includes
#include "CreateTetrahedralMeshCLP.h"
#include "benderIOUtils.h"
#include "vtkBrokenCells.h"

// ITK includes
#include "itkBinaryThresholdImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkImageFileWriter.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIterator.h"
#include "itkRelabelComponentImageFilter.h"
#include "itkConstantPadImageFilter.h"

// Slicer includes
#include "itkPluginUtilities.h"

// VTK includes
#include <vtkCleanPolyData.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkTetra.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkPolyData.h>
#include <vtkPolyDataWriter.h>
#include <vtkMath.h>
#include <vtkNew.h>
#include <vtkSmartPointer.h>

// Cleaver includes
#include <Cleaver/Cleaver.h>
#include <Cleaver/InverseField.h>
#include <Cleaver/PaddedVolume.h>
#include <Cleaver/ScalarField.h>
#include <Cleaver/Volume.h>
#include <LabelMapField.h>

// Use an anonymous namespace to keep class types and function names
// from colliding when module is used as shared object module.  Every
// thing should be in an anonymous namespace except for the module
// entry point, e.g. main()
//
namespace
{
template <class T> int DoIt( int argc, char * argv[] );

std::vector<Cleaver::LabelMapField::ImageType::Pointer> SplitLabelMaps(
  int    argc,
  char * argv[]);
} // end of anonymous namespace

int main( int argc, char * argv[] )
{

  PARSE_ARGS;

  itk::ImageIOBase::IOPixelType     pixelType;
  itk::ImageIOBase::IOComponentType componentType;

  try
    {
    itk::GetImageType(InputVolume, pixelType, componentType);

    switch( componentType )
      {
    case itk::ImageIOBase::UCHAR:
      return DoIt<unsigned char>( argc, argv );
      break;
    case itk::ImageIOBase::CHAR:
      return DoIt<char>( argc, argv );
      break;
    case itk::ImageIOBase::USHORT:
      return DoIt<unsigned short>( argc, argv );
      break;
    case itk::ImageIOBase::SHORT:
      return DoIt<short>( argc, argv );
      break;
    case itk::ImageIOBase::UINT:
      return DoIt<unsigned int>( argc, argv );
      break;
    case itk::ImageIOBase::INT:
      return DoIt<int>( argc, argv );
      break;
    case itk::ImageIOBase::ULONG:
      return DoIt<unsigned long>( argc, argv );
      break;
    case itk::ImageIOBase::LONG:
      return DoIt<long>( argc, argv );
      break;
    case itk::ImageIOBase::FLOAT:
      return DoIt<float>( argc, argv );
      break;
    case itk::ImageIOBase::DOUBLE:
      return DoIt<double>( argc, argv );
      break;
    case itk::ImageIOBase::UNKNOWNCOMPONENTTYPE:
    default:
      std::cerr << "Unknown component type: " << componentType << std::endl;
      break;
      }
    }

  catch( itk::ExceptionObject & excep )
    {
    std::cerr << argv[0] << ": exception caught !" << std::endl;
    std::cerr << excep << std::endl;
    return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}

// Use an anonymous namespace to keep class types and function names
// from colliding when module is used as shared object module.  Every
// thing should be in an anonymous namespace except for the module
// entry point, e.g. main()
//
namespace
{
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
std::vector<Cleaver::LabelMapField::ImageType::Pointer >
SplitLabelMaps(Cleaver::LabelMapField::ImageType *image, bool verbose)
{

  typedef Cleaver::LabelMapField::ImageType LabelImageType;
  typedef itk::RelabelComponentImageFilter<LabelImageType,
                                           LabelImageType> RelabelFilterType;
  typedef itk::BinaryThresholdImageFilter<LabelImageType,
                                          LabelImageType> ThresholdFilterType;
  typedef itk::ImageFileWriter<LabelImageType> ImageWriterType;

  // Assign continuous labels to the connected components, background is
  // considered to be 0 and will be ignored in the relabeling process.
  RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
  relabelFilter->SetInput( image );
  relabelFilter->Update();

  if (verbose)
    {
    std::cout << "Total Number of Labels: " <<
      relabelFilter->GetNumberOfObjects() << std::endl;
    }

  // Extract the labels
  typedef RelabelFilterType::LabelType LabelType;
  ThresholdFilterType::Pointer skinThresholdFilter =
    ThresholdFilterType::New();

  // Create a list of images corresponding to labels
  std::vector<LabelImageType::Pointer> labels;

  // The skin label will become background for internal (smaller) organs
  skinThresholdFilter->SetInput(relabelFilter->GetOutput());
  skinThresholdFilter->SetLowerThreshold(1);
  skinThresholdFilter->SetUpperThreshold(relabelFilter->GetNumberOfObjects()+1);
  skinThresholdFilter->SetInsideValue(-1);
  skinThresholdFilter->SetOutsideValue(0);
  skinThresholdFilter->Update();
  labels.push_back(skinThresholdFilter->GetOutput());

  for (LabelType i = 1, end = relabelFilter->GetNumberOfObjects()+1; i < end;
       ++i)
    {
    ThresholdFilterType::Pointer organThresholdFilter =
      ThresholdFilterType::New();
    organThresholdFilter->SetInput(relabelFilter->GetOutput());
    organThresholdFilter->SetLowerThreshold(i);
    organThresholdFilter->SetUpperThreshold(i);
    organThresholdFilter->SetInsideValue(i);
    organThresholdFilter->SetOutsideValue(-1);
    organThresholdFilter->Update();

    labels.push_back(organThresholdFilter->GetOutput());
    }

  return labels;
}

//----------------------------------------------------------------------------
bool IsPointInvalid(Cleaver::vec3 pos)
{
  return vtkBrokenCells::IsPointValid(pos.x, pos.y, pos.z);
}

//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
template <class T>
int DoIt( int argc, char * argv[] )
{

  PARSE_ARGS;

  typedef Cleaver::LabelMapField::ImageType LabelImageType;
  typedef T InputPixelType;
  typedef itk::Image<InputPixelType,3> InputImageType;
  typedef itk::CastImageFilter<InputImageType,
                               LabelImageType> CastFilterType;
  typedef itk::ImageFileReader<InputImageType> ReaderType;
  typedef itk::ConstantPadImageFilter<InputImageType,
                                      InputImageType> ConstantPadType;

  typename ReaderType::Pointer reader            = ReaderType::New();
  reader->SetFileName( InputVolume );
  reader->Update();

  typename CastFilterType::Pointer castingFilter = CastFilterType::New();
  castingFilter->SetInput(reader->GetOutput());

  std::vector<Cleaver::ScalarField*> labelMaps;

  std::vector<LabelImageType::Pointer> labels =
    SplitLabelMaps(castingFilter->GetOutput(), Verbose);

  // Get a map from the original labels to the new labels
  std::map<InputPixelType, InputPixelType> originalLabels;

  for(size_t i = 0; i < labels.size(); ++i)
    {
    itk::ImageRegionConstIterator<InputImageType> imageIterator(
      reader->GetOutput(), reader->GetOutput()->GetLargestPossibleRegion());
    itk::ImageRegionConstIterator<LabelImageType> labelsIterator(
      labels[i], labels[i]->GetLargestPossibleRegion());
    bool foundCorrespondence = false;
    while(!imageIterator.IsAtEnd()
      && !labelsIterator.IsAtEnd()
      && !foundCorrespondence)
      {
      if (labelsIterator.Value() > 0)
        {
        originalLabels[labelsIterator.Value()] = imageIterator.Value();
        }

      ++imageIterator;
      ++labelsIterator;
      }
    }

  if (Verbose)
    {
    std::cout << "Total labels found:  " << labels.size() << std::endl;
    }
  for(size_t i = 0; i < labels.size(); ++i)
    {
    labelMaps.push_back(new Cleaver::LabelMapField(labels[i]));
    static_cast<Cleaver::LabelMapField*>(labelMaps.back())->
      SetGenerateDataFromLabels(true);
    }

  if(labelMaps.empty())
    {
    std::cerr << "Failed to load image data. Terminating." << std::endl;
    return 0;
    }
  if(labelMaps.size() < 2)
    {
    labelMaps.push_back(new Cleaver::InverseField(labelMaps[0]));
    }

  Cleaver::AbstractVolume *volume = new Cleaver::Volume(labelMaps);
  if (Padding)
    {
    volume = new Cleaver::PaddedVolume(volume);
    }

  if (Verbose)
    {
    std::cout << "Creating Mesh with Volume Size "
      << volume->size().toString() << std::endl;
    }

  //--------------------------------
  //  Create Mesher & TetMesh
  //--------------------------------
  Cleaver::TetMesh *cleaverMesh =
    Cleaver::createMeshFromVolume(volume, Verbose);
  if (!cleaverMesh)
    {
    // Clean up
    delete volume;
    delete cleaverMesh;

    std::cerr << "Mesh computation failed !" << std::endl;
    return EXIT_FAILURE;
    }

  //------------------
  //  Compute Angles
  //------------------
  if(Verbose)
    {
    cleaverMesh->computeAngles();
    std::cout.precision(12);
    std::cout << "Worst Angles:" << std::endl;
    std::cout << "min: " << cleaverMesh->min_angle << std::endl;
    std::cout << "max: " << cleaverMesh->max_angle << std::endl;
    }

  //-----------------------
  //  Fill polydata arrays
  //-----------------------
  // Constants for undesired material
  const int airLabel = 0;
  int paddedVolumeLabel = labels.size();

  // Points and cell arrays
  vtkNew<vtkCellArray> meshTetras;
  vtkNew<vtkPoints> points;
  points->SetNumberOfPoints(cleaverMesh->tets.size() * 4);

  vtkNew<vtkIntArray> cellData;
  cellData->SetName("Labels");

  vtkNew<vtkBrokenCells> brokenCells;
  brokenCells->SetPoints(points.GetPointer());
  brokenCells->SetVerbose(Verbose);
  for(size_t i = 0; i < cleaverMesh->tets.size(); ++i)
    {
    int label = cleaverMesh->tets[i]->mat_label;

    if(label == airLabel || label == paddedVolumeLabel)
      {
      continue;
      }

    vtkNew<vtkTetra> meshTetra;
    for (int j = 0; j < 4; ++j)
      {
      Cleaver::vec3 &pos = cleaverMesh->tets[i]->verts[j]->pos();
      int vertexIndex = cleaverMesh->tets[i]->verts[j]->tm_v_index;

      points->SetPoint(vertexIndex, pos.x, pos.y, pos.z);
      meshTetra->GetPointIds()->SetId(j, vertexIndex);

      // If invalid, flag the cell so it can be rebuild later
      if (! IsPointInvalid(pos))
        {
        std::cerr << "Invalid point for cell " << i
          << ", this point will be patched up but something went wrong with"
          << " Cleaver !" << std::endl;
        brokenCells->AddCell(vertexIndex, meshTetra.GetPointer());
        }
      }

    meshTetras->InsertNextCell(meshTetra.GetPointer());
    cellData->InsertNextValue(originalLabels[label]);
    }

  //  Repair broken cells
  if (! brokenCells->RepairAllCells())
    {
    delete volume;
    delete cleaverMesh;
    return EXIT_FAILURE;
    }

  //-----------------------------
  //  Create and clean polydata
  //-----------------------------

  vtkSmartPointer<vtkPolyData> vtkMesh = vtkSmartPointer<vtkPolyData>::New();
  vtkMesh->SetPoints(points.GetPointer());
  vtkMesh->SetPolys(meshTetras.GetPointer());
  vtkMesh->GetCellData()->SetScalars(cellData.GetPointer());

  vtkNew<vtkCleanPolyData> cleanFilter;
  cleanFilter->PointMergingOff(); // Prevent from creating triangles or lines
  cleanFilter->SetInput(vtkMesh);

  //---------------------------------------
  //  Transform polydata to fit the image
  //---------------------------------------
  // Since cleaver does not take into account the image properties such as
  // spacing or origin, we need to transform the output points so the mesh can
  // match the original image.
  vtkNew<vtkTransform> transform;
  LabelImageType::SpacingType spacing = reader->GetOutput()->GetSpacing();
  LabelImageType::PointType origin = reader->GetOutput()->GetOrigin();
  LabelImageType::DirectionType imageDirection =
    reader->GetOutput()->GetDirection();

  // Transform points to RAS (what is concatenated first is done last !)
  vtkNew<vtkMatrix4x4> rasMatrix;
  rasMatrix->Identity();
  rasMatrix->SetElement(0, 0, -1.0);
  rasMatrix->SetElement(1, 1, -1.0);
  transform->Concatenate(rasMatrix.GetPointer());

  // Translation
  vtkNew<vtkMatrix4x4> directionMatrix;
  directionMatrix->Identity();
  for (int i = 0; i < imageDirection.RowDimensions; ++i)
    {
    for (int j = 0; j < imageDirection.ColumnDimensions; ++j)
      {
      directionMatrix->SetElement(i, j, imageDirection[i][j]);
      }
    }

  vtkNew<vtkTransform> offsetTransform;
  offsetTransform->Concatenate(directionMatrix.GetPointer());
  double offsets[3];
  if (Padding)
    {
    for (int i = 0; i < 3; ++i)
      {
      offsets[i] =
        spacing[i]*Cleaver::PaddedVolume::DefaultThickness + spacing[i]/2.0;
      }
    }
  else
    {
    for (int i = 0; i < 3; ++i)
      {
      offsets[i] = spacing[i] / 2.0;
      }
    }
  double* transformedOffsets = offsetTransform->TransformDoubleVector(offsets);
  transform->Translate(
    origin[0] - transformedOffsets[0],
    origin[1] - transformedOffsets[1],
    origin[2] - transformedOffsets[2]);

  // Scaling and rotation
  vtkNew<vtkMatrix4x4> scaleMatrix;
  scaleMatrix->DeepCopy(directionMatrix.GetPointer());
  for (int i = 0; i < spacing.GetNumberOfComponents(); ++i)
    {
    scaleMatrix->SetElement(i, i, scaleMatrix->GetElement(i, i) * spacing[i]);
    }
  transform->Concatenate(scaleMatrix.GetPointer());

  // Actual transformation
  vtkNew<vtkTransformPolyDataFilter> transformFilter;
  transformFilter->SetInput(cleanFilter->GetOutput());
  transformFilter->SetTransform(transform.GetPointer());

  bender::IOUtils::WritePolyData(transformFilter->GetOutput(), OutputMesh);

  // Clean up
  delete volume;
  delete cleaverMesh;

  return EXIT_SUCCESS;
}

} // end of anonymous namespace

<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/
#include <mitkContourModelMapper3D.h>

#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkProperty.h>

mitk::ContourModelMapper3D::ContourModelMapper3D()
{
}

mitk::ContourModelMapper3D::~ContourModelMapper3D()
{
}

const mitk::ContourModel* mitk::ContourModelMapper3D::GetInput( void )
{
  //convient way to get the data from the dataNode
  return static_cast< const mitk::ContourModel * >( this->GetData() );
}

vtkProp* mitk::ContourModelMapper3D::GetVtkProp(mitk::BaseRenderer* renderer)
{
  //return the actor corresponding to the renderer
  return m_LSH.GetLocalStorage(renderer)->m_Actor;
}

void mitk::ContourModelMapper3D::MitkRenderOverlay(BaseRenderer* renderer)
{
  if ( this->IsVisible(renderer)==false )
    return;
  if ( this->GetVtkProp(renderer)->GetVisibility() )
  {
    this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer());
  }
}

void mitk::ContourModelMapper3D::MitkRenderOpaqueGeometry(BaseRenderer* renderer)
{
  if ( this->IsVisible( renderer )==false )
    return;
  if ( this->GetVtkProp(renderer)->GetVisibility() )
  {
    this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() );
  }
}

void mitk::ContourModelMapper3D::MitkRenderTranslucentGeometry(BaseRenderer* renderer)
{
  if ( this->IsVisible(renderer)==false )
    return;
  if ( this->GetVtkProp(renderer)->GetVisibility() )
  {
    this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer());
  }
}

void mitk::ContourModelMapper3D::MitkRenderVolumetricGeometry(BaseRenderer* renderer)
{
  if(IsVisible(renderer)==false)
    return;
  if ( GetVtkProp(renderer)->GetVisibility() )
  {
    this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer());
  }
}

void mitk::ContourModelMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
  /* First convert the contourModel to vtkPolyData, then tube filter it and
   * set it input for our mapper
   */

  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

  mitk::ContourModel* inputContour  = static_cast< mitk::ContourModel* >( this->GetData() );

  localStorage->m_OutlinePolyData = this->CreateVtkPolyDataFromContour(inputContour);

  this->ApplyContourProperties(renderer);

  //tube filter the polyData
  localStorage->m_TubeFilter->SetInput(localStorage->m_OutlinePolyData);

  float lineWidth(1.0);
  if (this->GetDataNode()->GetFloatProperty( "3D contour width", lineWidth, renderer ))
  {
    localStorage->m_TubeFilter->SetRadius(lineWidth);
  }else
  {
    localStorage->m_TubeFilter->SetRadius(0.2);
  }
  localStorage->m_TubeFilter->CappingOn();
  localStorage->m_TubeFilter->SetNumberOfSides(10);
  localStorage->m_TubeFilter->Update();
  localStorage->m_Mapper->SetInput(localStorage->m_TubeFilter->GetOutput());

}

void mitk::ContourModelMapper3D::Update(mitk::BaseRenderer* renderer)
{
  if ( !this->IsVisible( renderer ) )
  {
    return;
  }

  mitk::ContourModel* data  = static_cast< mitk::ContourModel*>( this->GetData() );
  if ( data == NULL )
  {
    return;
  }

  // Calculate time step of the input data for the specified renderer (integer value)
  this->CalculateTimeStep( renderer );

  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
  // Check if time step is valid
  const TimeSlicedGeometry *dataTimeGeometry = data->GetTimeSlicedGeometry();
  if ( ( dataTimeGeometry == NULL )
    || ( dataTimeGeometry->GetTimeSteps() == 0 )
    || ( !dataTimeGeometry->IsValidTime( renderer->GetTimeStep() ) ) )
  {
    //clear the rendered polydata
    localStorage->m_Mapper->SetInput(vtkSmartPointer<vtkPolyData>::New());
    return;
  }

  const DataNode *node = this->GetDataNode();
  data->UpdateOutputInformation();

  //check if something important has changed and we need to rerender
  if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified?
    || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified?
    || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified?
    || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->GetMTime())
    || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified?
    || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) )
  {
    this->GenerateDataForRenderer( renderer );
  }

  // since we have checked that nothing important has changed, we can set
  // m_LastUpdateTime to the current time
  localStorage->m_LastUpdateTime.Modified();
}

vtkSmartPointer<vtkPolyData> mitk::ContourModelMapper3D::CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour)
{
  unsigned int timestep = this->GetTimestep();

  //the points to draw
  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  //the lines to connect the points
  vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
  // Create a polydata to store everything in
  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();

  //iterate over the control points
  mitk::ContourModel::VertexIterator current = inputContour->IteratorBegin(timestep);
  mitk::ContourModel::VertexIterator next = inputContour->IteratorBegin(timestep);
  if(next != inputContour->IteratorEnd(timestep))
  {
    next++;

    mitk::ContourModel::VertexIterator end = inputContour->IteratorEnd(timestep);

    while(next != end)
    {
      mitk::ContourModel::VertexType* currentControlPoint = *current;
      mitk::ContourModel::VertexType* nextControlPoint = *next;

      vtkIdType p1 = points->InsertNextPoint(currentControlPoint->Coordinates[0], currentControlPoint->Coordinates[1], currentControlPoint->Coordinates[2]);
      vtkIdType p2 = points->InsertNextPoint(nextControlPoint->Coordinates[0], nextControlPoint->Coordinates[1], nextControlPoint->Coordinates[2]);
      //add the line between both contorlPoints
      lines->InsertNextCell(2);
      lines->InsertCellPoint(p1);
      lines->InsertCellPoint(p2);

      current++;
      next++;
    }

    if(inputContour->IsClosed(timestep))
    {
      // If the contour is closed add a line from the last to the first control point
      mitk::ContourModel::VertexType* firstControlPoint = *(inputContour->IteratorBegin(timestep));
      mitk::ContourModel::VertexType* lastControlPoint = *(--(inputContour->IteratorEnd(timestep)));
      vtkIdType p2 = points->InsertNextPoint(lastControlPoint->Coordinates[0], lastControlPoint->Coordinates[1], lastControlPoint->Coordinates[2]);
      vtkIdType p1 = points->InsertNextPoint(firstControlPoint->Coordinates[0], firstControlPoint->Coordinates[1], firstControlPoint->Coordinates[2]);

      //add the line to the cellArray
      lines->InsertNextCell(2);
      lines->InsertCellPoint(p1);
      lines->InsertCellPoint(p2);
    }

    // Add the points to the dataset
    polyData->SetPoints(points);
    // Add the lines to the dataset
    polyData->SetLines(lines);
  }
  return polyData;
}

void mitk::ContourModelMapper3D::ApplyContourProperties(mitk::BaseRenderer* renderer)
{
  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

  mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(GetDataNode()->GetProperty
        ("color", renderer));
  if(colorprop)
  {
    //set the color of the contour
    double red = colorprop->GetColor().GetRed();
    double green = colorprop->GetColor().GetGreen();
    double blue = colorprop->GetColor().GetBlue();
    localStorage->m_Actor->GetProperty()->SetColor(red, green, blue);
  }
}

/*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/

mitk::ContourModelMapper3D::LocalStorage* mitk::ContourModelMapper3D::GetLocalStorage(mitk::BaseRenderer* renderer)
{
  return m_LSH.GetLocalStorage(renderer);
}

mitk::ContourModelMapper3D::LocalStorage::LocalStorage()
{
  m_Mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  m_Actor = vtkSmartPointer<vtkActor>::New();
  m_OutlinePolyData = vtkSmartPointer<vtkPolyData>::New();
  m_TubeFilter = vtkSmartPointer<vtkTubeFilter>::New();

  //set the mapper for the actor
  m_Actor->SetMapper(m_Mapper);
}

void mitk::ContourModelMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
  node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite );
  node->AddProperty( "3D contour width", mitk::FloatProperty::New( 0.2 ), renderer, overwrite );

  Superclass::SetDefaultProperties(node, renderer, overwrite);
}<commit_msg>*temporarly* check for duplicate points<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/
#include <mitkContourModelMapper3D.h>

#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkProperty.h>

mitk::ContourModelMapper3D::ContourModelMapper3D()
{
}

mitk::ContourModelMapper3D::~ContourModelMapper3D()
{
}

const mitk::ContourModel* mitk::ContourModelMapper3D::GetInput( void )
{
  //convient way to get the data from the dataNode
  return static_cast< const mitk::ContourModel * >( this->GetData() );
}

vtkProp* mitk::ContourModelMapper3D::GetVtkProp(mitk::BaseRenderer* renderer)
{
  //return the actor corresponding to the renderer
  return m_LSH.GetLocalStorage(renderer)->m_Actor;
}

void mitk::ContourModelMapper3D::MitkRenderOverlay(BaseRenderer* renderer)
{
  if ( this->IsVisible(renderer)==false )
    return;
  if ( this->GetVtkProp(renderer)->GetVisibility() )
  {
    this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer());
  }
}

void mitk::ContourModelMapper3D::MitkRenderOpaqueGeometry(BaseRenderer* renderer)
{
  if ( this->IsVisible( renderer )==false )
    return;
  if ( this->GetVtkProp(renderer)->GetVisibility() )
  {
    this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() );
  }
}

void mitk::ContourModelMapper3D::MitkRenderTranslucentGeometry(BaseRenderer* renderer)
{
  if ( this->IsVisible(renderer)==false )
    return;
  if ( this->GetVtkProp(renderer)->GetVisibility() )
  {
    this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer());
  }
}

void mitk::ContourModelMapper3D::MitkRenderVolumetricGeometry(BaseRenderer* renderer)
{
  if(IsVisible(renderer)==false)
    return;
  if ( GetVtkProp(renderer)->GetVisibility() )
  {
    this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer());
  }
}

void mitk::ContourModelMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
  /* First convert the contourModel to vtkPolyData, then tube filter it and
   * set it input for our mapper
   */

  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

  mitk::ContourModel* inputContour  = static_cast< mitk::ContourModel* >( this->GetData() );

  localStorage->m_OutlinePolyData = this->CreateVtkPolyDataFromContour(inputContour);

  this->ApplyContourProperties(renderer);

  //tube filter the polyData
  localStorage->m_TubeFilter->SetInput(localStorage->m_OutlinePolyData);

  float lineWidth(1.0);
  if (this->GetDataNode()->GetFloatProperty( "3D contour width", lineWidth, renderer ))
  {
    localStorage->m_TubeFilter->SetRadius(lineWidth);
  }else
  {
    localStorage->m_TubeFilter->SetRadius(0.2);
  }
  localStorage->m_TubeFilter->CappingOn();
  localStorage->m_TubeFilter->SetNumberOfSides(10);
  localStorage->m_TubeFilter->Update();
  localStorage->m_Mapper->SetInput(localStorage->m_TubeFilter->GetOutput());

}

void mitk::ContourModelMapper3D::Update(mitk::BaseRenderer* renderer)
{
  if ( !this->IsVisible( renderer ) )
  {
    return;
  }

  mitk::ContourModel* data  = static_cast< mitk::ContourModel*>( this->GetData() );
  if ( data == NULL )
  {
    return;
  }

  // Calculate time step of the input data for the specified renderer (integer value)
  this->CalculateTimeStep( renderer );

  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
  // Check if time step is valid
  const TimeSlicedGeometry *dataTimeGeometry = data->GetTimeSlicedGeometry();
  if ( ( dataTimeGeometry == NULL )
    || ( dataTimeGeometry->GetTimeSteps() == 0 )
    || ( !dataTimeGeometry->IsValidTime( renderer->GetTimeStep() ) ) )
  {
    //clear the rendered polydata
    localStorage->m_Mapper->SetInput(vtkSmartPointer<vtkPolyData>::New());
    return;
  }

  const DataNode *node = this->GetDataNode();
  data->UpdateOutputInformation();

  //check if something important has changed and we need to rerender
  if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified?
    || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified?
    || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified?
    || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->GetMTime())
    || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified?
    || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) )
  {
    this->GenerateDataForRenderer( renderer );
  }

  // since we have checked that nothing important has changed, we can set
  // m_LastUpdateTime to the current time
  localStorage->m_LastUpdateTime.Modified();
}

vtkSmartPointer<vtkPolyData> mitk::ContourModelMapper3D::CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour)
{
  unsigned int timestep = this->GetTimestep();

  //the points to draw
  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  //the lines to connect the points
  vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
  // Create a polydata to store everything in
  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();

  //iterate over the control points
  mitk::ContourModel::VertexIterator current = inputContour->IteratorBegin(timestep);
  mitk::ContourModel::VertexIterator next = inputContour->IteratorBegin(timestep);
  if(next != inputContour->IteratorEnd(timestep))
  {
    next++;

    mitk::ContourModel::VertexIterator end = inputContour->IteratorEnd(timestep);

    while(next != end)
    {
      mitk::ContourModel::VertexType* currentControlPoint = *current;
      mitk::ContourModel::VertexType* nextControlPoint = *next;

      if( currentControlPoint->Coordinates[0] != nextControlPoint->Coordinates[0] &&
          currentControlPoint->Coordinates[1] != nextControlPoint->Coordinates[1] &&
          currentControlPoint->Coordinates[2] != nextControlPoint->Coordinates[2])
      {
        vtkIdType p1 = points->InsertNextPoint(currentControlPoint->Coordinates[0], currentControlPoint->Coordinates[1], currentControlPoint->Coordinates[2]);
        vtkIdType p2 = points->InsertNextPoint(nextControlPoint->Coordinates[0], nextControlPoint->Coordinates[1], nextControlPoint->Coordinates[2]);
        //add the line between both contorlPoints
        lines->InsertNextCell(2);
        lines->InsertCellPoint(p1);
        lines->InsertCellPoint(p2);
      }
      current++;
      next++;
    }

    if(inputContour->IsClosed(timestep))
    {
      // If the contour is closed add a line from the last to the first control point
      mitk::ContourModel::VertexType* firstControlPoint = *(inputContour->IteratorBegin(timestep));
      mitk::ContourModel::VertexType* lastControlPoint = *(--(inputContour->IteratorEnd(timestep)));
      if( lastControlPoint->Coordinates[0] != firstControlPoint->Coordinates[0] &&
          lastControlPoint->Coordinates[1] != firstControlPoint->Coordinates[1] &&
          lastControlPoint->Coordinates[2] != firstControlPoint->Coordinates[2])
      {
        vtkIdType p2 = points->InsertNextPoint(lastControlPoint->Coordinates[0], lastControlPoint->Coordinates[1], lastControlPoint->Coordinates[2]);
        vtkIdType p1 = points->InsertNextPoint(firstControlPoint->Coordinates[0], firstControlPoint->Coordinates[1], firstControlPoint->Coordinates[2]);

        //add the line to the cellArray
        lines->InsertNextCell(2);
        lines->InsertCellPoint(p1);
        lines->InsertCellPoint(p2);
      }
    }

    // Add the points to the dataset
    polyData->SetPoints(points);
    // Add the lines to the dataset
    polyData->SetLines(lines);
  }
  return polyData;
}

void mitk::ContourModelMapper3D::ApplyContourProperties(mitk::BaseRenderer* renderer)
{
  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

  mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(GetDataNode()->GetProperty
        ("color", renderer));
  if(colorprop)
  {
    //set the color of the contour
    double red = colorprop->GetColor().GetRed();
    double green = colorprop->GetColor().GetGreen();
    double blue = colorprop->GetColor().GetBlue();
    localStorage->m_Actor->GetProperty()->SetColor(red, green, blue);
  }
}

/*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/

mitk::ContourModelMapper3D::LocalStorage* mitk::ContourModelMapper3D::GetLocalStorage(mitk::BaseRenderer* renderer)
{
  return m_LSH.GetLocalStorage(renderer);
}

mitk::ContourModelMapper3D::LocalStorage::LocalStorage()
{
  m_Mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  m_Actor = vtkSmartPointer<vtkActor>::New();
  m_OutlinePolyData = vtkSmartPointer<vtkPolyData>::New();
  m_TubeFilter = vtkSmartPointer<vtkTubeFilter>::New();

  //set the mapper for the actor
  m_Actor->SetMapper(m_Mapper);
}

void mitk::ContourModelMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
  node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite );
  node->AddProperty( "3D contour width", mitk::FloatProperty::New( 0.2 ), renderer, overwrite );

  Superclass::SetDefaultProperties(node, renderer, overwrite);
}<|endoftext|>


<commit_before>#include "stdafx.h"

#include <sstream>

#include "Game.h"
#include "Klingon.h"
#include "Galaxy.h"

namespace StarTrek {

Random Game::generator;

Game::Game() : e_(10000), t_(8) {
    Game::generator = &rand;
}

void Game::fireWeapon(Galaxy& galaxy) {
	if (galaxy.parameter("command") == "phaser") {
        firePhaser(galaxy);
	} else if (galaxy.parameter("command") == "photon") {
        firePhoton(galaxy);
	}
}

void Game::firePhaser(Galaxy& galaxy) {
		int amount = atoi(galaxy.parameter("amount").c_str());
		Klingon* enemy = (Klingon*)galaxy.variable("target");
		if (e_ >= amount) {
			int distance = enemy->distance();
			if (distance > 4000) {
				stringstream message;
				message << "Klingon out of range of phasers at " << distance << " sectors...";
				galaxy.writeLine(message.str());
			} else {
				int damage = amount - (((amount /20)* distance /200) + rnd(200));
				if (damage < 1)
					damage = 1;
				stringstream message;
				message << "Phasers hit Klingon at " << distance << " sectors with " << damage << " units";
				galaxy.writeLine(message.str());
				if (damage < enemy->energy()) {
					enemy->energy(enemy->energy() - damage);
					stringstream message;
					message << "Klingon has " << enemy->energy() << " remaining";
					galaxy.writeLine(message.str());
				} else {
					galaxy.writeLine("Klingon destroyed!");
					enemy->destroy();
				}
			}
			e_ -= amount;

		} else {
			galaxy.writeLine("Insufficient energy to fire phasers!");
		}
}

void Game::firePhoton(Galaxy& galaxy) {
    Klingon* enemy = (Klingon*)galaxy.variable("target");
    if (t_ > 0) {
        int distance = enemy->distance();
        if ((rnd(4) + ((distance / 500) + 1) > 7)) {
            stringstream message;
            message << "Torpedo missed Klingon at " << distance << " sectors...";
            galaxy.writeLine(message.str());
        } else {
            int damage = 800 + rnd(50);
            stringstream message;
            message << "Photons hit Klingon at " << distance << " sectors with " << damage << " units";
            galaxy.writeLine(message.str());

            if (damage < enemy->energy()) {
                enemy->energy(enemy->energy() - damage);
                stringstream message;
                message << "Klingon has " << enemy->energy() << " remaining";
                galaxy.writeLine(message.str());
            } else {
                galaxy.writeLine("Klingon destroyed!");
                enemy->destroy();
            }
        }
        t_--;

    } else {
        galaxy.writeLine("No more photon torpedoes!");
    }
}

void Game::fireWeapon(Untouchables::WebGadget* webGadget) {
    Galaxy galaxy(webGadget);
    fireWeapon(galaxy);
}

int Game::energyRemaining(void) {
    return e_;
}

int Game::torpedoes(void) {
    return t_;
}

void Game::torpedoes(int value) {
    t_ = value;
}

}
<commit_msg>Fix indentation<commit_after>#include "stdafx.h"

#include <sstream>

#include "Game.h"
#include "Klingon.h"
#include "Galaxy.h"

namespace StarTrek {

Random Game::generator;

Game::Game() : e_(10000), t_(8) {
    Game::generator = &rand;
}

void Game::fireWeapon(Galaxy& galaxy) {
	if (galaxy.parameter("command") == "phaser") {
        firePhaser(galaxy);
	} else if (galaxy.parameter("command") == "photon") {
        firePhoton(galaxy);
	}
}

void Game::firePhaser(Galaxy& galaxy) {
    int amount = atoi(galaxy.parameter("amount").c_str());
    Klingon* enemy = (Klingon*)galaxy.variable("target");
    if (e_ >= amount) {
        int distance = enemy->distance();
        if (distance > 4000) {
            stringstream message;
            message << "Klingon out of range of phasers at " << distance << " sectors...";
            galaxy.writeLine(message.str());
        } else {
            int damage = amount - (((amount /20)* distance /200) + rnd(200));
            if (damage < 1)
                damage = 1;
            stringstream message;
            message << "Phasers hit Klingon at " << distance << " sectors with " << damage << " units";
            galaxy.writeLine(message.str());
            if (damage < enemy->energy()) {
                enemy->energy(enemy->energy() - damage);
                stringstream message;
                message << "Klingon has " << enemy->energy() << " remaining";
                galaxy.writeLine(message.str());
            } else {
                galaxy.writeLine("Klingon destroyed!");
                enemy->destroy();
            }
        }
        e_ -= amount;

    } else {
        galaxy.writeLine("Insufficient energy to fire phasers!");
    }
}

void Game::firePhoton(Galaxy& galaxy) {
    Klingon* enemy = (Klingon*)galaxy.variable("target");
    if (t_ > 0) {
        int distance = enemy->distance();
        if ((rnd(4) + ((distance / 500) + 1) > 7)) {
            stringstream message;
            message << "Torpedo missed Klingon at " << distance << " sectors...";
            galaxy.writeLine(message.str());
        } else {
            int damage = 800 + rnd(50);
            stringstream message;
            message << "Photons hit Klingon at " << distance << " sectors with " << damage << " units";
            galaxy.writeLine(message.str());

            if (damage < enemy->energy()) {
                enemy->energy(enemy->energy() - damage);
                stringstream message;
                message << "Klingon has " << enemy->energy() << " remaining";
                galaxy.writeLine(message.str());
            } else {
                galaxy.writeLine("Klingon destroyed!");
                enemy->destroy();
            }
        }
        t_--;

    } else {
        galaxy.writeLine("No more photon torpedoes!");
    }
}

void Game::fireWeapon(Untouchables::WebGadget* webGadget) {
    Galaxy galaxy(webGadget);
    fireWeapon(galaxy);
}

int Game::energyRemaining(void) {
    return e_;
}

int Game::torpedoes(void) {
    return t_;
}

void Game::torpedoes(int value) {
    t_ = value;
}

}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkImageMomentsTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2000 National Library of Medicine
  All rights reserved.

  See COPYRIGHT.txt for copyright details.

=========================================================================*/

#include "itkAffineTransform.h"
#include "itkImage.h"
#include "itkImageMoments.h"
#include "itkIndex.h"
#include "itkSize.h"

int
main(
    int argc,
    char *argv[])
{
    /* Define acceptable (absolute) error in computed results.
       All the calculations are done in double and are well-conditioned,
       so we should be able to get within a few epsilon of the right
       values.  So choose maxerr to be 10*epsilon for IEEE 754 double. */
    double maxerr = 1.0e-15;

    /* Define the image size and physical coordinates */
    itk::Size<3> size = {{20, 40, 80}};
    double origin [3] = { 0.5,   0.5,   0.5};
    double spacing[3] = { 0.1,   0.05 , 0.025};

    /* Define positions of the test masses in index coordinates */
    unsigned short mass = 1;           // Test mass
    long point[8][3] = {
	{ 10+8, 20+12, 40+0},
	{ 10-8, 20-12, 40-0},
	{ 10+3, 20-8,  40+0},
	{ 10-3, 20+8,  40-0},
	{ 10+0, 20+0,  40+10},
	{ 10-0, 20-0,  40-10},
    };

    /* Define the expected (true) results for comparison */
    double ttm = 6.0;                      // Total mass
    double cgd[3] = {1.5,   1.5, 1.5 };    // Center of gravity
    double pmd[3] = {0.125, 0.5, 2.0 };    // Principal moments
    double pad[3][3] = {                   // Principal axes
	{ 0.0,  0.0, 1.0},
	{ 0.6, -0.8, 0.0},
	{ 0.8,  0.6, 0.0},
    };
    vnl_vector_fixed<double,3> tcg;
    tcg.set(cgd);
    vnl_vector_fixed<double,3> tpm;
    tpm.set(pmd);
    vnl_matrix_fixed<double,3,3> tpa;
    tpa.set((double *)pad);

    /* Allocate a simple test image */
    itk::Image<unsigned short, 3>::Pointer
      image = itk::Image<unsigned short,3>::New();
    itk::Image<unsigned short, 3>::RegionType region;
    region.SetSize(size);
    image->SetLargestPossibleRegion(region);
    image->SetBufferedRegion(region);

    /* Set origin and spacing of physical coordinates */
    image->SetOrigin(origin);
    image->SetSpacing(spacing);
    image->Allocate();

    /* Set a few mass points within the image */
    /* FIXME: The method used here to set the points is klutzy,
       but appears to be the only method currently supported. */
    itk::Index<3> index;          /* Index over pixels */
    for ( int i = 0; i < 6; i++) {
	index.SetIndex(point[i]);
	image->SetPixel(index, mass);
    }

    /* Compute the moments */
    itk::ImageMoments<unsigned short, 3>
	moments(image);
    double ctm = moments.GetTotalMass();
    vnl_vector_fixed<double,3>
        ccg = moments.GetCenterOfGravity();
    vnl_vector_fixed<double,3>
        cpm = moments.GetPrincipalMoments();
    vnl_matrix_fixed<double,3,3>
        cpa = moments.GetPrincipalAxes();

    /* Report the various non-central moments */
    // FIXME:  Indentation is not handled correctly in matrix output
    std::cout << "\nTotal mass = " << ctm << "\n";
    std::cout << "True total mass = " << ttm << "\n";
    std::cout << "\nFirst moments about index origin =\n";
    std::cout << "   " << moments.GetFirstMoments() << "\n";
    std::cout << "\nSecond moments about index origin =\n";
    std::cout << "   " << moments.GetSecondMoments() << "\n";

    /* Report the center of gravity and central moments */
    std::cout << "\nCenter of gravity =\n";
    std::cout << "   " << ccg << "\n";
    std::cout << "True center of gravity =\n";
    std::cout << "   " << tcg << "\n";
    std::cout << "\nSecond central moments =\n";
    std::cout << "   " << moments.GetCentralMoments() << "\n";

    /* Report principal moments and axes */
    std::cout << "\nPrincipal moments = \n";
    std::cout << "   " << cpm << "\n";
    std::cout << "True principal moments = \n";
    std::cout << "   " << tpm << "\n";
    std::cout << "\nPrincipal axes = \n";
    std::cout << "   " << cpa << "\n";
    std::cout << "True principal axes = \n";
    std::cout << "   " << tpa << "\n";

    /* Compute transforms between principal and physical axes */
    /* FIXME: Automatically check correctness of these results? */
    itk::ImageMoments<unsigned short, 3>::AffineTransformType
        pa2p = moments.GetPrincipalAxesToPhysicalAxesTransform();
    std::cout << "\nPrincipal axes to physical axes transform:\n";
    std::cout << pa2p << std::endl;
    itk::ImageMoments<unsigned short, 3>::AffineTransformType
        p2pa = moments.GetPhysicalAxesToPrincipalAxesTransform();
    std::cout << "\nPhysical axes to principal axes transform:\n";
    std::cout << p2pa << std::endl;

    /* Do some error checking on the transforms */
    double dist = pa2p.Metric(pa2p);
    std::cout << "Distance from self to self = " << dist << std::endl;
    itk::ImageMoments<unsigned short, 3>::AffineTransformType
        p2pa2p;
    p2pa2p.Compose(p2pa);
    p2pa2p.Compose(pa2p);
    double trerr = p2pa2p.Metric();
    std::cout << "Distance from composition to identity = ";
    std::cout << trerr << std::endl;

    /* Compute and report max abs error in computed */
    double tmerr = abs(ttm - ctm);  // Error in total mass
    double cgerr = 0.0;             // Error in center of gravity
    double pmerr = 0.0;             // Error in moments
    double paerr = 0.0;             // Error in axes
    for ( int i = 0; i < 3; ++i) {
        if ( abs(ccg[i] - tcg[i]) > cgerr )
            cgerr = abs(ccg[i] - tcg[i]);
        if ( abs(cpm[i] - tpm[i]) > pmerr )
            pmerr = abs(cpm[i] - tpm[i]);
        for (int j = 0; j < 3; ++j) {
            if (abs(cpa[i][j] - tpa[i][j]) > paerr)
                paerr = abs(cpa[i][j] - tpa[i][j]);
        }
    }
    std::cout << "\nErrors found in:\n";
    std::cout << "   Total mass        = " << tmerr << std::endl;
    std::cout << "   Center of gravity = " << cgerr << std::endl;
    std::cout << "   Principal moments = " << pmerr << std::endl;
    std::cout << "   Principal axes    = " << paerr << std::endl;
    std::cout << "   Transformations   = " << trerr << std::endl;

    /* Return error if differences are too large */
    int stat =
        tmerr > maxerr || cgerr > maxerr ||
        pmerr > maxerr || paerr > maxerr ||
        trerr > maxerr;
    if (stat)
        std::cout << "\n*** Errors are larger than defined maximum value.\n";
    else
        std::cout << "\n*** Errors are acceptable.\n";
    return stat;
}
<commit_msg>ERR: long  -> unsigned long<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkImageMomentsTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2000 National Library of Medicine
  All rights reserved.

  See COPYRIGHT.txt for copyright details.

=========================================================================*/

#include "itkAffineTransform.h"
#include "itkImage.h"
#include "itkImageMoments.h"
#include "itkIndex.h"
#include "itkSize.h"

int
main(
    int argc,
    char *argv[])
{
    /* Define acceptable (absolute) error in computed results.
       All the calculations are done in double and are well-conditioned,
       so we should be able to get within a few epsilon of the right
       values.  So choose maxerr to be 10*epsilon for IEEE 754 double. */
    double maxerr = 1.0e-15;

    /* Define the image size and physical coordinates */
    itk::Size<3> size = {{20, 40, 80}};
    double origin [3] = { 0.5,   0.5,   0.5};
    double spacing[3] = { 0.1,   0.05 , 0.025};

    /* Define positions of the test masses in index coordinates */
    unsigned short mass = 1;           // Test mass
    unsigned long point[8][3] = {
	{ 10+8, 20+12, 40+0},
	{ 10-8, 20-12, 40-0},
	{ 10+3, 20-8,  40+0},
	{ 10-3, 20+8,  40-0},
	{ 10+0, 20+0,  40+10},
	{ 10-0, 20-0,  40-10},
    };

    /* Define the expected (true) results for comparison */
    double ttm = 6.0;                      // Total mass
    double cgd[3] = {1.5,   1.5, 1.5 };    // Center of gravity
    double pmd[3] = {0.125, 0.5, 2.0 };    // Principal moments
    double pad[3][3] = {                   // Principal axes
	{ 0.0,  0.0, 1.0},
	{ 0.6, -0.8, 0.0},
	{ 0.8,  0.6, 0.0},
    };
    vnl_vector_fixed<double,3> tcg;
    tcg.set(cgd);
    vnl_vector_fixed<double,3> tpm;
    tpm.set(pmd);
    vnl_matrix_fixed<double,3,3> tpa;
    tpa.set((double *)pad);

    /* Allocate a simple test image */
    itk::Image<unsigned short, 3>::Pointer
      image = itk::Image<unsigned short,3>::New();
    itk::Image<unsigned short, 3>::RegionType region;
    region.SetSize(size);
    image->SetLargestPossibleRegion(region);
    image->SetBufferedRegion(region);

    /* Set origin and spacing of physical coordinates */
    image->SetOrigin(origin);
    image->SetSpacing(spacing);
    image->Allocate();

    /* Set a few mass points within the image */
    /* FIXME: The method used here to set the points is klutzy,
       but appears to be the only method currently supported. */
    itk::Index<3> index;          /* Index over pixels */
    for ( int i = 0; i < 6; i++) {
	index.SetIndex(point[i]);
	image->SetPixel(index, mass);
    }

    /* Compute the moments */
    itk::ImageMoments<unsigned short, 3>
	moments(image);
    double ctm = moments.GetTotalMass();
    vnl_vector_fixed<double,3>
        ccg = moments.GetCenterOfGravity();
    vnl_vector_fixed<double,3>
        cpm = moments.GetPrincipalMoments();
    vnl_matrix_fixed<double,3,3>
        cpa = moments.GetPrincipalAxes();

    /* Report the various non-central moments */
    // FIXME:  Indentation is not handled correctly in matrix output
    std::cout << "\nTotal mass = " << ctm << "\n";
    std::cout << "True total mass = " << ttm << "\n";
    std::cout << "\nFirst moments about index origin =\n";
    std::cout << "   " << moments.GetFirstMoments() << "\n";
    std::cout << "\nSecond moments about index origin =\n";
    std::cout << "   " << moments.GetSecondMoments() << "\n";

    /* Report the center of gravity and central moments */
    std::cout << "\nCenter of gravity =\n";
    std::cout << "   " << ccg << "\n";
    std::cout << "True center of gravity =\n";
    std::cout << "   " << tcg << "\n";
    std::cout << "\nSecond central moments =\n";
    std::cout << "   " << moments.GetCentralMoments() << "\n";

    /* Report principal moments and axes */
    std::cout << "\nPrincipal moments = \n";
    std::cout << "   " << cpm << "\n";
    std::cout << "True principal moments = \n";
    std::cout << "   " << tpm << "\n";
    std::cout << "\nPrincipal axes = \n";
    std::cout << "   " << cpa << "\n";
    std::cout << "True principal axes = \n";
    std::cout << "   " << tpa << "\n";

    /* Compute transforms between principal and physical axes */
    /* FIXME: Automatically check correctness of these results? */
    itk::ImageMoments<unsigned short, 3>::AffineTransformType
        pa2p = moments.GetPrincipalAxesToPhysicalAxesTransform();
    std::cout << "\nPrincipal axes to physical axes transform:\n";
    std::cout << pa2p << std::endl;
    itk::ImageMoments<unsigned short, 3>::AffineTransformType
        p2pa = moments.GetPhysicalAxesToPrincipalAxesTransform();
    std::cout << "\nPhysical axes to principal axes transform:\n";
    std::cout << p2pa << std::endl;

    /* Do some error checking on the transforms */
    double dist = pa2p.Metric(pa2p);
    std::cout << "Distance from self to self = " << dist << std::endl;
    itk::ImageMoments<unsigned short, 3>::AffineTransformType
        p2pa2p;
    p2pa2p.Compose(p2pa);
    p2pa2p.Compose(pa2p);
    double trerr = p2pa2p.Metric();
    std::cout << "Distance from composition to identity = ";
    std::cout << trerr << std::endl;

    /* Compute and report max abs error in computed */
    double tmerr = abs(ttm - ctm);  // Error in total mass
    double cgerr = 0.0;             // Error in center of gravity
    double pmerr = 0.0;             // Error in moments
    double paerr = 0.0;             // Error in axes
    for ( int i = 0; i < 3; ++i) {
        if ( abs(ccg[i] - tcg[i]) > cgerr )
            cgerr = abs(ccg[i] - tcg[i]);
        if ( abs(cpm[i] - tpm[i]) > pmerr )
            pmerr = abs(cpm[i] - tpm[i]);
        for (int j = 0; j < 3; ++j) {
            if (abs(cpa[i][j] - tpa[i][j]) > paerr)
                paerr = abs(cpa[i][j] - tpa[i][j]);
        }
    }
    std::cout << "\nErrors found in:\n";
    std::cout << "   Total mass        = " << tmerr << std::endl;
    std::cout << "   Center of gravity = " << cgerr << std::endl;
    std::cout << "   Principal moments = " << pmerr << std::endl;
    std::cout << "   Principal axes    = " << paerr << std::endl;
    std::cout << "   Transformations   = " << trerr << std::endl;

    /* Return error if differences are too large */
    int stat =
        tmerr > maxerr || cgerr > maxerr ||
        pmerr > maxerr || paerr > maxerr ||
        trerr > maxerr;
    if (stat)
        std::cout << "\n*** Errors are larger than defined maximum value.\n";
    else
        std::cout << "\n*** Errors are acceptable.\n";
    return stat;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Medical Imaging & Interaction Toolkit
  Module:    $RCSfile$
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/ for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include <sstream>
#include "QmitkDataTreeViewItem.h"
#include "mitkPropertyList.h"
#include "mitkStringProperty.h"
#include "enabled.xpm"
#include "disabled.xpm"
QmitkDataTreeViewItem::QmitkDataTreeViewItem( QListView *parent, const QString &s1 , const QString &s2 , mitk::DataTreeIteratorBase* nodeIt )
    : QListViewItem( parent, s1, s2 ),m_DataTreeIteratorBase(NULL)
{
  assert(nodeIt!=NULL);
  m_DataTreeIteratorBase = nodeIt;

  m_TreeNode = nodeIt->Get();
  QListViewItem::setText(0,QString("All Datasets"));

  mitk::DataTreeChildIterator it(nodeIt->GetTree(), nodeIt->GetNode());
  while (!it.IsAtEnd())
  {
    QmitkDataTreeViewItem * nextItem = new QmitkDataTreeViewItem(this,&it);
    ++it;
  }
  setOpen(true);
}

QmitkDataTreeViewItem::QmitkDataTreeViewItem( QmitkDataTreeViewItem * parent, mitk::DataTreeIteratorBase * nodeIt )
: QListViewItem(parent),m_DataTreeIteratorBase(NULL)
{
  assert(nodeIt!=NULL);
  m_DataTreeIteratorBase = nodeIt;

  m_TreeNode = nodeIt->Get();
  char name[256];

  if (m_TreeNode->GetName(*name, NULL)) {
	  QListViewItem::setText(0,QString(name));
  } else {
	  QListViewItem::setText(0,"No name!");
  }

  std::stringstream ss;
  ss << m_TreeNode->GetReferenceCount() << "/";
  mitk::BaseData::ConstPointer bd = m_TreeNode->GetData();
   if (bd.IsNotNull()) {
	  QListViewItem::setText(1,QString(bd->GetNameOfClass())) ;
     ss << m_TreeNode->GetData()->GetReferenceCount();
   } else {
	  QListViewItem::setText(1,QString("empty DataTreeNode"));
	ss << "-";
  }

  QListViewItem::setText(2,QString(ss.str().c_str()));
  mitk::DataTreeChildIterator it(nodeIt->GetTree(), nodeIt->GetNode());
  while (!it.IsAtEnd())
  {
    QmitkDataTreeViewItem * nextItem = new QmitkDataTreeViewItem(this,&it);
    ++it;
  }
  setOpen(true);
}

mitk::DataTreeNode::ConstPointer QmitkDataTreeViewItem::GetDataTreeNode() const {
	return m_TreeNode;
}

void QmitkNodeViewBaseItem::updateEnabledAppearance() {
      static const QPixmap enabledPix((const char **)enabled_xpm);
      static const QPixmap disabledPix((const char **)disabled_xpm);
      // ok, we are instanceof QListViewItem, but the cast
      // is ugly:
      QListViewItem* listViewItem = NULL;
      listViewItem = dynamic_cast<NodeViewPropertyItem*>(this);
      if ((listViewItem = dynamic_cast<NodeViewPropertyItem*>(this)) ||
	  (listViewItem = dynamic_cast<NodeViewCheckboxItem*>(this))) {
	if (isPropEnabled()) {
	  listViewItem->setPixmap(0,enabledPix);
	} else {
	  listViewItem->setPixmap(0,disabledPix);

	}

      }
    }
<commit_msg>use new simpler constructors of DataTreeChildIterator<commit_after>/*=========================================================================

  Program:   Medical Imaging & Interaction Toolkit
  Module:    $RCSfile$
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/ for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include <sstream>
#include "QmitkDataTreeViewItem.h"
#include "mitkPropertyList.h"
#include "mitkStringProperty.h"
#include "enabled.xpm"
#include "disabled.xpm"
QmitkDataTreeViewItem::QmitkDataTreeViewItem( QListView *parent, const QString &s1 , const QString &s2 , mitk::DataTreeIteratorBase* nodeIt )
    : QListViewItem( parent, s1, s2 ),m_DataTreeIteratorBase(NULL)
{
  assert(nodeIt!=NULL);
  m_DataTreeIteratorBase = nodeIt;

  m_TreeNode = nodeIt->Get();
  QListViewItem::setText(0,QString("All Datasets"));

  mitk::DataTreeChildIterator it(*nodeIt);
  while (!it.IsAtEnd())
  {
    QmitkDataTreeViewItem * nextItem = new QmitkDataTreeViewItem(this,&it);
    ++it;
  }
  setOpen(true);
}

QmitkDataTreeViewItem::QmitkDataTreeViewItem( QmitkDataTreeViewItem * parent, mitk::DataTreeIteratorBase * nodeIt )
: QListViewItem(parent),m_DataTreeIteratorBase(NULL)
{
  assert(nodeIt!=NULL);
  m_DataTreeIteratorBase = nodeIt;

  m_TreeNode = nodeIt->Get();
  char name[256];

  if (m_TreeNode->GetName(*name, NULL)) {
	  QListViewItem::setText(0,QString(name));
  } else {
	  QListViewItem::setText(0,"No name!");
  }

  std::stringstream ss;
  ss << m_TreeNode->GetReferenceCount() << "/";
  mitk::BaseData::ConstPointer bd = m_TreeNode->GetData();
   if (bd.IsNotNull()) {
	  QListViewItem::setText(1,QString(bd->GetNameOfClass())) ;
     ss << m_TreeNode->GetData()->GetReferenceCount();
   } else {
	  QListViewItem::setText(1,QString("empty DataTreeNode"));
	ss << "-";
  }

  QListViewItem::setText(2,QString(ss.str().c_str()));
  mitk::DataTreeChildIterator it(*nodeIt);
  while (!it.IsAtEnd())
  {
    QmitkDataTreeViewItem * nextItem = new QmitkDataTreeViewItem(this,&it);
    ++it;
  }
  setOpen(true);
}

mitk::DataTreeNode::ConstPointer QmitkDataTreeViewItem::GetDataTreeNode() const {
	return m_TreeNode;
}

void QmitkNodeViewBaseItem::updateEnabledAppearance() {
      static const QPixmap enabledPix((const char **)enabled_xpm);
      static const QPixmap disabledPix((const char **)disabled_xpm);
      // ok, we are instanceof QListViewItem, but the cast
      // is ugly:
      QListViewItem* listViewItem = NULL;
      listViewItem = dynamic_cast<NodeViewPropertyItem*>(this);
      if ((listViewItem = dynamic_cast<NodeViewPropertyItem*>(this)) ||
	  (listViewItem = dynamic_cast<NodeViewCheckboxItem*>(this))) {
	if (isPropEnabled()) {
	  listViewItem->setPixmap(0,enabledPix);
	} else {
	  listViewItem->setPixmap(0,disabledPix);

	}

      }
    }
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/renderer_host/gtk_key_bindings_handler.h"

#include <gdk/gdkkeysyms.h>
#include <string>
#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/edit_command.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "testing/gtest/include/gtest/gtest.h"

class GtkKeyBindingsHandlerTest : public testing::Test {
 protected:
  struct EditCommand {
    const char* name;
    const char* value;
  };

  GtkKeyBindingsHandlerTest()
      : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
        handler_(NULL) {
    FilePath gtkrc;
    PathService::Get(chrome::DIR_TEST_DATA, &gtkrc);
    gtkrc = gtkrc.AppendASCII("gtk_key_bindings_test_gtkrc");

    gtk_rc_parse(gtkrc.value().c_str());

    GtkWidget* fixed = gtk_fixed_new();
    handler_ = new GtkKeyBindingsHandler(fixed);
    gtk_container_add(GTK_CONTAINER(window_), fixed);
    gtk_widget_show(fixed);
    gtk_widget_show(window_);
  }
  ~GtkKeyBindingsHandlerTest() {
    gtk_widget_destroy(window_);
    delete handler_;
  }

  NativeWebKeyboardEvent NewNativeWebKeyboardEvent(guint keyval, guint state) {
    GdkKeymap* keymap =
        gdk_keymap_get_for_display(gtk_widget_get_display(window_));

    GdkKeymapKey *keys = NULL;
    gint n_keys = 0;
    if (gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &n_keys)) {
      GdkEventKey event;
      event.type = GDK_KEY_PRESS;
      event.window = NULL;
      event.send_event = 0;
      event.time = 0;
      event.state = state;
      event.keyval = keyval;
      event.length = 0;
      event.string = NULL;
      event.hardware_keycode = keys[0].keycode;
      event.group = keys[0].group;
      event.is_modifier = 0;
      g_free(keys);
      return NativeWebKeyboardEvent(&event);
    }
    LOG(ERROR) << "Failed to create key event for keyval:" << keyval;
    return NativeWebKeyboardEvent();
  }

  void TestKeyBinding(const NativeWebKeyboardEvent& event,
                      const EditCommand expected_result[],
                      size_t size) {
    EditCommands result;
    ASSERT_TRUE(handler_->Match(event, &result));
    ASSERT_EQ(size, result.size());
    for (size_t i = 0; i < size; ++i) {
      ASSERT_STREQ(expected_result[i].name, result[i].name.c_str());
      ASSERT_STREQ(expected_result[i].value, result[i].value.c_str());
    }
  }

 protected:
  GtkWidget* window_;
  GtkKeyBindingsHandler* handler_;
};

// Does not work in a chroot. See bug 60363.
TEST_F(GtkKeyBindingsHandlerTest, FAILS_MoveCursor) {
  static const EditCommand kEditCommands[] = {
    // "move-cursor" (logical-positions, -2, 0)
    { "MoveBackward", "" },
    { "MoveBackward", "" },
    // "move-cursor" (logical-positions, 2, 0)
    { "MoveForward", "" },
    { "MoveForward", "" },
    // "move-cursor" (visual-positions, -1, 1)
    { "MoveLeftAndModifySelection", "" },
    // "move-cursor" (visual-positions, 1, 1)
    { "MoveRightAndModifySelection", "" },
    // "move-cursor" (words, -1, 0)
    { "MoveWordBackward", "" },
    // "move-cursor" (words, 1, 0)
    { "MoveWordForward", "" },
    // "move-cursor" (display-lines, -1, 0)
    { "MoveUp", "" },
    // "move-cursor" (display-lines, 1, 0)
    { "MoveDown", "" },
    // "move-cursor" (display-line-ends, -1, 0)
    { "MoveToBeginningOfLine", "" },
    // "move-cursor" (display-line-ends, 1, 0)
    { "MoveToEndOfLine", "" },
    // "move-cursor" (paragraph-ends, -1, 0)
    { "MoveToBeginningOfParagraph", "" },
    // "move-cursor" (paragraph-ends, 1, 0)
    { "MoveToEndOfParagraph", "" },
    // "move-cursor" (pages, -1, 0)
    { "MovePageUp", "" },
    // "move-cursor" (pages, 1, 0)
    { "MovePageDown", "" },
    // "move-cursor" (buffer-ends, -1, 0)
    { "MoveToBeginningOfDocument", "" },
    // "move-cursor" (buffer-ends, 1, 0)
    { "MoveToEndOfDocument", "" }
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_1, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

// Does not work in a chroot. See bug 60363.
TEST_F(GtkKeyBindingsHandlerTest, FAILS_DeleteFromCursor) {
  static const EditCommand kEditCommands[] = {
    // "delete-from-cursor" (chars, -2)
    { "DeleteBackward", "" },
    { "DeleteBackward", "" },
    // "delete-from-cursor" (chars, 2)
    { "DeleteForward", "" },
    { "DeleteForward", "" },
    // "delete-from-cursor" (word-ends, -1)
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (word-ends, 1)
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, -1)
    { "MoveWordBackward", "" },
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, 1)
    { "MoveWordForward", "" },
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (display-lines, -1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-lines, 1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-line-ends, -1)
    { "DeleteToBeginningOfLine", "" },
    // "delete-from-cursor" (display-line-ends, 1)
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (paragraph-ends, -1)
    { "DeleteToBeginningOfParagraph", "" },
    // "delete-from-cursor" (paragraph-ends, 1)
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, -1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, 1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_2, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

// Does not work in a chroot. See bug 60363.
TEST_F(GtkKeyBindingsHandlerTest, FAILS_OtherActions) {
  static const EditCommand kBackspace[] = {
    { "DeleteBackward", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_3, GDK_CONTROL_MASK),
                 kBackspace, arraysize(kBackspace));

  static const EditCommand kCopyClipboard[] = {
    { "Copy", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_4, GDK_CONTROL_MASK),
                 kCopyClipboard, arraysize(kCopyClipboard));

  static const EditCommand kCutClipboard[] = {
    { "Cut", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_5, GDK_CONTROL_MASK),
                 kCutClipboard, arraysize(kCutClipboard));

  static const EditCommand kInsertAtCursor[] = {
    { "InsertText", "hello" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_6, GDK_CONTROL_MASK),
                 kInsertAtCursor, arraysize(kInsertAtCursor));

  static const EditCommand kPasteClipboard[] = {
    { "Paste", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_7, GDK_CONTROL_MASK),
                 kPasteClipboard, arraysize(kPasteClipboard));

  static const EditCommand kSelectAll[] = {
    { "Unselect", "" },
    { "SelectAll", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_8, GDK_CONTROL_MASK),
                 kSelectAll, arraysize(kSelectAll));

  static const EditCommand kSetAnchor[] = {
    { "SetMark", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_9, GDK_CONTROL_MASK),
                 kSetAnchor, arraysize(kSetAnchor));
}
<commit_msg>GtkKeyBindingsTest.* do not fail anymore.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/renderer_host/gtk_key_bindings_handler.h"

#include <gdk/gdkkeysyms.h>
#include <string>
#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/edit_command.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "testing/gtest/include/gtest/gtest.h"

class GtkKeyBindingsHandlerTest : public testing::Test {
 protected:
  struct EditCommand {
    const char* name;
    const char* value;
  };

  GtkKeyBindingsHandlerTest()
      : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
        handler_(NULL) {
    FilePath gtkrc;
    PathService::Get(chrome::DIR_TEST_DATA, &gtkrc);
    gtkrc = gtkrc.AppendASCII("gtk_key_bindings_test_gtkrc");

    gtk_rc_parse(gtkrc.value().c_str());

    GtkWidget* fixed = gtk_fixed_new();
    handler_ = new GtkKeyBindingsHandler(fixed);
    gtk_container_add(GTK_CONTAINER(window_), fixed);
    gtk_widget_show(fixed);
    gtk_widget_show(window_);
  }
  ~GtkKeyBindingsHandlerTest() {
    gtk_widget_destroy(window_);
    delete handler_;
  }

  NativeWebKeyboardEvent NewNativeWebKeyboardEvent(guint keyval, guint state) {
    GdkKeymap* keymap =
        gdk_keymap_get_for_display(gtk_widget_get_display(window_));

    GdkKeymapKey *keys = NULL;
    gint n_keys = 0;
    if (gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &n_keys)) {
      GdkEventKey event;
      event.type = GDK_KEY_PRESS;
      event.window = NULL;
      event.send_event = 0;
      event.time = 0;
      event.state = state;
      event.keyval = keyval;
      event.length = 0;
      event.string = NULL;
      event.hardware_keycode = keys[0].keycode;
      event.group = keys[0].group;
      event.is_modifier = 0;
      g_free(keys);
      return NativeWebKeyboardEvent(&event);
    }
    LOG(ERROR) << "Failed to create key event for keyval:" << keyval;
    return NativeWebKeyboardEvent();
  }

  void TestKeyBinding(const NativeWebKeyboardEvent& event,
                      const EditCommand expected_result[],
                      size_t size) {
    EditCommands result;
    ASSERT_TRUE(handler_->Match(event, &result));
    ASSERT_EQ(size, result.size());
    for (size_t i = 0; i < size; ++i) {
      ASSERT_STREQ(expected_result[i].name, result[i].name.c_str());
      ASSERT_STREQ(expected_result[i].value, result[i].value.c_str());
    }
  }

 protected:
  GtkWidget* window_;
  GtkKeyBindingsHandler* handler_;
};

TEST_F(GtkKeyBindingsHandlerTest, MoveCursor) {
  static const EditCommand kEditCommands[] = {
    // "move-cursor" (logical-positions, -2, 0)
    { "MoveBackward", "" },
    { "MoveBackward", "" },
    // "move-cursor" (logical-positions, 2, 0)
    { "MoveForward", "" },
    { "MoveForward", "" },
    // "move-cursor" (visual-positions, -1, 1)
    { "MoveLeftAndModifySelection", "" },
    // "move-cursor" (visual-positions, 1, 1)
    { "MoveRightAndModifySelection", "" },
    // "move-cursor" (words, -1, 0)
    { "MoveWordBackward", "" },
    // "move-cursor" (words, 1, 0)
    { "MoveWordForward", "" },
    // "move-cursor" (display-lines, -1, 0)
    { "MoveUp", "" },
    // "move-cursor" (display-lines, 1, 0)
    { "MoveDown", "" },
    // "move-cursor" (display-line-ends, -1, 0)
    { "MoveToBeginningOfLine", "" },
    // "move-cursor" (display-line-ends, 1, 0)
    { "MoveToEndOfLine", "" },
    // "move-cursor" (paragraph-ends, -1, 0)
    { "MoveToBeginningOfParagraph", "" },
    // "move-cursor" (paragraph-ends, 1, 0)
    { "MoveToEndOfParagraph", "" },
    // "move-cursor" (pages, -1, 0)
    { "MovePageUp", "" },
    // "move-cursor" (pages, 1, 0)
    { "MovePageDown", "" },
    // "move-cursor" (buffer-ends, -1, 0)
    { "MoveToBeginningOfDocument", "" },
    // "move-cursor" (buffer-ends, 1, 0)
    { "MoveToEndOfDocument", "" }
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_1, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

TEST_F(GtkKeyBindingsHandlerTest, DeleteFromCursor) {
  static const EditCommand kEditCommands[] = {
    // "delete-from-cursor" (chars, -2)
    { "DeleteBackward", "" },
    { "DeleteBackward", "" },
    // "delete-from-cursor" (chars, 2)
    { "DeleteForward", "" },
    { "DeleteForward", "" },
    // "delete-from-cursor" (word-ends, -1)
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (word-ends, 1)
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, -1)
    { "MoveWordBackward", "" },
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, 1)
    { "MoveWordForward", "" },
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (display-lines, -1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-lines, 1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-line-ends, -1)
    { "DeleteToBeginningOfLine", "" },
    // "delete-from-cursor" (display-line-ends, 1)
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (paragraph-ends, -1)
    { "DeleteToBeginningOfParagraph", "" },
    // "delete-from-cursor" (paragraph-ends, 1)
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, -1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, 1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_2, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

TEST_F(GtkKeyBindingsHandlerTest, OtherActions) {
  static const EditCommand kBackspace[] = {
    { "DeleteBackward", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_3, GDK_CONTROL_MASK),
                 kBackspace, arraysize(kBackspace));

  static const EditCommand kCopyClipboard[] = {
    { "Copy", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_4, GDK_CONTROL_MASK),
                 kCopyClipboard, arraysize(kCopyClipboard));

  static const EditCommand kCutClipboard[] = {
    { "Cut", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_5, GDK_CONTROL_MASK),
                 kCutClipboard, arraysize(kCutClipboard));

  static const EditCommand kInsertAtCursor[] = {
    { "InsertText", "hello" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_6, GDK_CONTROL_MASK),
                 kInsertAtCursor, arraysize(kInsertAtCursor));

  static const EditCommand kPasteClipboard[] = {
    { "Paste", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_7, GDK_CONTROL_MASK),
                 kPasteClipboard, arraysize(kPasteClipboard));

  static const EditCommand kSelectAll[] = {
    { "Unselect", "" },
    { "SelectAll", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_8, GDK_CONTROL_MASK),
                 kSelectAll, arraysize(kSelectAll));

  static const EditCommand kSetAnchor[] = {
    { "SetMark", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_9, GDK_CONTROL_MASK),
                 kSetAnchor, arraysize(kSetAnchor));
}
<|endoftext|>


<commit_before>#include <sigma/opengl/shader_technique.hpp>

#include <sigma/opengl/render_uniforms.hpp>
#include <sigma/opengl/shader.hpp>
#include <sigma/opengl/texture.hpp>
#include <sigma/opengl/util.hpp>

#include <glm/gtc/type_ptr.hpp>

#include <cassert>
#include <iostream>

namespace sigma {
namespace opengl {
    shader_technique::shader_technique()
    {
        GL_CHECK(object_ = glCreateProgram());
    }

    shader_technique::~shader_technique()
    {
        glDeleteProgram(object_);
    }

    void shader_technique::attach(std::shared_ptr<shader> shdr)
    {
        assert(linked_ == GL_FALSE && "Can not add shaders to already linked programs");
        GL_CHECK(glAttachShader(object_, shdr->get_object()));
        shaders_.push_back(shdr);
    }

    void shader_technique::link()
    {
        assert(linked_ == GL_FALSE && "Program already linked");
        GL_CHECK(glLinkProgram(object_));

        glGetProgramiv(object_, GL_LINK_STATUS, &linked_);
        if (linked_ == GL_FALSE) {
            std::cerr << "shader program: link faild" << std::endl;
            // TODO get the link message.
            std::abort();
        }

        GL_CHECK(glUseProgram(object_));
        GL_CHECK(projection_matrix_location_ = glGetUniformLocation(object_, PROJECTION_MATRIX_NAME));
        GL_CHECK(view_matrix_location_ = glGetUniformLocation(object_, VIEW_MATRIX_NAME));
        GL_CHECK(model_matrix_location_ = glGetUniformLocation(object_, MODEL_MATRIX_NAME));
        GL_CHECK(model_view_matrix_location_ = glGetUniformLocation(object_, MODEL_VIEW_MATRIX_NAME));
        GL_CHECK(normal_matrix_location_ = glGetUniformLocation(object_, NORMAL_MATRIX_NAME));
        GL_CHECK(z_near_location_ = glGetUniformLocation(object_, Z_NEAR_NAME));
        GL_CHECK(z_far_location_ = glGetUniformLocation(object_, Z_FAR_NAME));
        GL_CHECK(view_port_size_location_ = glGetUniformLocation(object_, VIEW_PORT_SIZE_NAME));
        GL_CHECK(time_location_ = glGetUniformLocation(object_, TIME_NAME));
    }

    GLint shader_technique::get_uniform_location(const char* name)
    {
        GL_CHECK(glUseProgram(object_));
        GL_CHECK(GLint loc = glGetUniformLocation(object_, name));
        return loc;
    }

    void shader_technique::set_texture(std::string name, std::shared_ptr<texture> txt)
    {
        auto it = texture_map_.find(name);
        if (it == texture_map_.end()) {
            auto ind = get_uniform_location(name.c_str());
            // TODO maybe warn about the texture not being used?
            //assert(ind >= 0 && "Program does not have this texture!");
            if (ind >= 0) {
                texture_map_[name] = textures_.size();
                textures_.push_back(std::make_pair(textures_.size(), txt));
            }
            return;
        }
        textures_[texture_map_[name]].second = txt;
    }

    void shader_technique::bind()
    {
        GL_CHECK(glUseProgram(object_));
    }

    void shader_technique::bind(render_matrices* matrices, texture_unit first_texture_unit)
    {
        GL_CHECK(glUseProgram(object_));
        auto size = textures_.size();
        for (uint32_t i = 0; i < size; ++i) {
            GL_CHECK(glUniform1i(textures_[i].first, i));
            GL_CHECK(glActiveTexture(GLenum(first_texture_unit) + i));
            textures_[i].second->bind();
        }

        GL_CHECK(glUniformMatrix4fv(projection_matrix_location_, 1, GL_FALSE, glm::value_ptr(matrices->projection_matrix)));
        GL_CHECK(glUniformMatrix4fv(view_matrix_location_, 1, GL_FALSE, glm::value_ptr(matrices->view_matrix)));
        GL_CHECK(glUniformMatrix4fv(model_matrix_location_, 1, GL_FALSE, glm::value_ptr(matrices->model_matrix)));
        GL_CHECK(glUniformMatrix4fv(model_view_matrix_location_, 1, GL_FALSE, glm::value_ptr(matrices->model_view_matrix)));
        GL_CHECK(glUniformMatrix3fv(normal_matrix_location_, 1, GL_FALSE, glm::value_ptr(matrices->normal_matrix)));
        GL_CHECK(glUniform1f(z_near_location_, matrices->z_near));
        GL_CHECK(glUniform1f(z_far_location_, matrices->z_far));
        GL_CHECK(glUniform2fv(view_port_size_location_, 1, glm::value_ptr(matrices->size)));
    }
}
}
<commit_msg>Was not useing the actual sampler location for binding textures.<commit_after>#include <sigma/opengl/shader_technique.hpp>

#include <sigma/opengl/render_uniforms.hpp>
#include <sigma/opengl/shader.hpp>
#include <sigma/opengl/texture.hpp>
#include <sigma/opengl/util.hpp>

#include <glm/gtc/type_ptr.hpp>

#include <cassert>
#include <iostream>

namespace sigma {
namespace opengl {
    shader_technique::shader_technique()
    {
        GL_CHECK(object_ = glCreateProgram());
    }

    shader_technique::~shader_technique()
    {
        glDeleteProgram(object_);
    }

    void shader_technique::attach(std::shared_ptr<shader> shdr)
    {
        assert(linked_ == GL_FALSE && "Can not add shaders to already linked programs");
        GL_CHECK(glAttachShader(object_, shdr->get_object()));
        shaders_.push_back(shdr);
    }

    void shader_technique::link()
    {
        assert(linked_ == GL_FALSE && "Program already linked");
        GL_CHECK(glLinkProgram(object_));

        glGetProgramiv(object_, GL_LINK_STATUS, &linked_);
        if (linked_ == GL_FALSE) {
            std::cerr << "shader program: link faild" << std::endl;
            // TODO get the link message.
            std::abort();
        }

        GL_CHECK(glUseProgram(object_));
        GL_CHECK(projection_matrix_location_ = glGetUniformLocation(object_, PROJECTION_MATRIX_NAME));
        GL_CHECK(view_matrix_location_ = glGetUniformLocation(object_, VIEW_MATRIX_NAME));
        GL_CHECK(model_matrix_location_ = glGetUniformLocation(object_, MODEL_MATRIX_NAME));
        GL_CHECK(model_view_matrix_location_ = glGetUniformLocation(object_, MODEL_VIEW_MATRIX_NAME));
        GL_CHECK(normal_matrix_location_ = glGetUniformLocation(object_, NORMAL_MATRIX_NAME));
        GL_CHECK(z_near_location_ = glGetUniformLocation(object_, Z_NEAR_NAME));
        GL_CHECK(z_far_location_ = glGetUniformLocation(object_, Z_FAR_NAME));
        GL_CHECK(view_port_size_location_ = glGetUniformLocation(object_, VIEW_PORT_SIZE_NAME));
        GL_CHECK(time_location_ = glGetUniformLocation(object_, TIME_NAME));
    }

    GLint shader_technique::get_uniform_location(const char* name)
    {
        GL_CHECK(glUseProgram(object_));
        GL_CHECK(GLint loc = glGetUniformLocation(object_, name));
        return loc;
    }

    void shader_technique::set_texture(std::string name, std::shared_ptr<texture> txt)
    {
        auto it = texture_map_.find(name);
        if (it == texture_map_.end()) {
            auto ind = get_uniform_location(name.c_str());
            // TODO maybe warn about the texture not being used?
            //assert(ind >= 0 && "Program does not have this texture!");
            if (ind >= 0) {
                texture_map_[name] = textures_.size();
                textures_.push_back(std::make_pair(ind, txt));
            }
            return;
        }
        textures_[texture_map_[name]].second = txt;
    }

    void shader_technique::bind()
    {
        GL_CHECK(glUseProgram(object_));
    }

    void shader_technique::bind(render_matrices* matrices, texture_unit first_texture_unit)
    {
        GL_CHECK(glUseProgram(object_));
        auto size = textures_.size();
        for (uint32_t i = 0; i < size; ++i) {
            GL_CHECK(glUniform1i(textures_[i].first, i));
            GL_CHECK(glActiveTexture(GLenum(first_texture_unit) + i));
            textures_[i].second->bind();
        }

        GL_CHECK(glUniformMatrix4fv(projection_matrix_location_, 1, GL_FALSE, glm::value_ptr(matrices->projection_matrix)));
        GL_CHECK(glUniformMatrix4fv(view_matrix_location_, 1, GL_FALSE, glm::value_ptr(matrices->view_matrix)));
        GL_CHECK(glUniformMatrix4fv(model_matrix_location_, 1, GL_FALSE, glm::value_ptr(matrices->model_matrix)));
        GL_CHECK(glUniformMatrix4fv(model_view_matrix_location_, 1, GL_FALSE, glm::value_ptr(matrices->model_view_matrix)));
        GL_CHECK(glUniformMatrix3fv(normal_matrix_location_, 1, GL_FALSE, glm::value_ptr(matrices->normal_matrix)));
        GL_CHECK(glUniform1f(z_near_location_, matrices->z_near));
        GL_CHECK(glUniform1f(z_far_location_, matrices->z_far));
        GL_CHECK(glUniform2fv(view_port_size_location_, 1, glm::value_ptr(matrices->size)));
    }
}
}
<|endoftext|>