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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

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

#include "mitkAffineTransform3D.h"
#include "mitkBaseGeometry.h"
#include "mitkGeometry3D.h"
#include "mitkInteractionConst.h"
#include "mitkLine.h"
#include "mitkPlaneGeometry.h"
#include "mitkRotationOperation.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkThinPlateSplineCurvedGeometry.h"

#include <mitkTestFixture.h>
#include <mitkTestingMacros.h>

#include <vnl/vnl_quaternion.h>
#include <vnl/vnl_quaternion.hxx>

#include <fstream>
#include <iomanip>
#include <mitkIOUtil.h>
#include <mitkImage.h>

static const mitk::ScalarType testEps = 1E-9; // the epsilon used in this test == at least float precision.

class mitkPlaneGeometryTestSuite : public mitk::TestFixture
{
  CPPUNIT_TEST_SUITE(mitkPlaneGeometryTestSuite);
  MITK_TEST(TestInitializeStandardPlane);
  MITK_TEST(TestProjectPointOntoPlane);
  MITK_TEST(TestPlaneGeometryCloning);
  MITK_TEST(TestInheritance);
  MITK_TEST(TestSetExtendInMM);
  MITK_TEST(TestRotate);
  MITK_TEST(TestClone);
  MITK_TEST(TestPlaneComparison);
  MITK_TEST(TestAxialInitialization);
  MITK_TEST(TestFrontalInitialization);
  MITK_TEST(TestSaggitalInitialization);
  MITK_TEST(TestLefthandedCoordinateSystem);
  MITK_TEST(TestDominantAxesError);
  MITK_TEST(TestCheckRotationMatrix);

  // Currently commented out, see See bug 15990
  // MITK_TEST(testPlaneGeometryInitializeOrder);
  MITK_TEST(TestIntersectionPoint);
  MITK_TEST(TestCase1210);

  CPPUNIT_TEST_SUITE_END();

private:
  // private test members that are initialized by setUp()
  mitk::PlaneGeometry::Pointer planegeometry;
  mitk::Point3D origin;
  mitk::Vector3D right, bottom, normal, spacing;
  mitk::ScalarType width, height;
  mitk::ScalarType widthInMM, heightInMM, thicknessInMM;

public:
  void setUp() override
  {
    planegeometry = mitk::PlaneGeometry::New();
    width = 100;
    widthInMM = width;
    height = 200;
    heightInMM = height;
    thicknessInMM = 1.0;
    mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
    mitk::FillVector3D(right, widthInMM, 0, 0);
    mitk::FillVector3D(bottom, 0, heightInMM, 0);
    mitk::FillVector3D(normal, 0, 0, thicknessInMM);
    mitk::FillVector3D(spacing, 1.0, 1.0, thicknessInMM);

    planegeometry->InitializeStandardPlane(right, bottom);
    planegeometry->SetOrigin(origin);
    planegeometry->SetSpacing(spacing);
  }

  void tearDown() override {}
  // This test verifies inheritance behaviour, this test will fail if the behaviour changes in the future
  void TestInheritance()
  {
    mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New();
    mitk::Geometry3D::Pointer g3d = dynamic_cast<mitk::Geometry3D *>(plane.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("Planegeometry should not be castable to Geometry 3D", g3d.IsNull());

    mitk::BaseGeometry::Pointer base = dynamic_cast<mitk::BaseGeometry *>(plane.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("Planegeometry should be castable to BaseGeometry", base.IsNotNull());

    g3d = mitk::Geometry3D::New();
    base = dynamic_cast<mitk::BaseGeometry *>(g3d.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("Geometry3D should be castable to BaseGeometry", base.IsNotNull());

    mitk::SlicedGeometry3D::Pointer sliced = mitk::SlicedGeometry3D::New();
    g3d = dynamic_cast<mitk::Geometry3D *>(sliced.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("SlicedGeometry3D should not be castable to Geometry3D", g3d.IsNull());

    mitk::ThinPlateSplineCurvedGeometry::Pointer thin = mitk::ThinPlateSplineCurvedGeometry::New();
    plane = dynamic_cast<mitk::PlaneGeometry *>(thin.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("AbstractTransformGeometry should be castable to PlaneGeometry", plane.IsNotNull());

    plane = mitk::PlaneGeometry::New();
    mitk::AbstractTransformGeometry::Pointer atg = dynamic_cast<mitk::AbstractTransformGeometry *>(plane.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("PlaneGeometry should not be castable to AbstractTransofrmGeometry", atg.IsNull());
  }

  void TestDominantAxesError()
  {
    auto image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("NotQuiteARotationMatrix.nrrd"));
    auto matrix = image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().transpose();
    std::vector< int > axes = mitk::PlaneGeometry::CalculateDominantAxes(matrix);
    CPPUNIT_ASSERT_MESSAGE("Domiant axes cannot be determined in this dataset. Output should be default ordering.", axes.at(0)==0 && axes.at(1)==1 && axes.at(2)==2);
  }

  void TestCheckRotationMatrix()
  {
    auto image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("NotQuiteARotationMatrix.nrrd"));
    bool is_rotation = mitk::PlaneGeometry::CheckRotationMatrix(image->GetGeometry()->GetIndexToWorldTransform());
    CPPUNIT_ASSERT_MESSAGE("Since the test data matrix is not quite a rotation matrix, this should be detected.", !is_rotation);
  }

  void TestLefthandedCoordinateSystem()
  {
    /**
     * @brief This method tests InitializeStandardPlane() and IndexToWorld()
     * with a left-handed coordinate orientation or indexToWorldMatrix.
     *
     * Of course this test does not use standard Parameters, which are right-handed.
     * See also discussion of bug #11477: http://bugs.mitk.org/show_bug.cgi?id=11477
     */
    planegeometry = mitk::PlaneGeometry::New();
    width = 100;
    widthInMM = 5;
    height = 200;<commit_msg>Use more strict epsilon on test data<commit_after>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

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

#include "mitkAffineTransform3D.h"
#include "mitkBaseGeometry.h"
#include "mitkGeometry3D.h"
#include "mitkInteractionConst.h"
#include "mitkLine.h"
#include "mitkPlaneGeometry.h"
#include "mitkRotationOperation.h"
#include "mitkSlicedGeometry3D.h"
#include "mitkThinPlateSplineCurvedGeometry.h"

#include <mitkTestFixture.h>
#include <mitkTestingMacros.h>

#include <vnl/vnl_quaternion.h>
#include <vnl/vnl_quaternion.hxx>

#include <fstream>
#include <iomanip>
#include <mitkIOUtil.h>
#include <mitkImage.h>

static const mitk::ScalarType testEps = 1E-9; // the epsilon used in this test == at least float precision.

class mitkPlaneGeometryTestSuite : public mitk::TestFixture
{
  CPPUNIT_TEST_SUITE(mitkPlaneGeometryTestSuite);
  MITK_TEST(TestInitializeStandardPlane);
  MITK_TEST(TestProjectPointOntoPlane);
  MITK_TEST(TestPlaneGeometryCloning);
  MITK_TEST(TestInheritance);
  MITK_TEST(TestSetExtendInMM);
  MITK_TEST(TestRotate);
  MITK_TEST(TestClone);
  MITK_TEST(TestPlaneComparison);
  MITK_TEST(TestAxialInitialization);
  MITK_TEST(TestFrontalInitialization);
  MITK_TEST(TestSaggitalInitialization);
  MITK_TEST(TestLefthandedCoordinateSystem);
  MITK_TEST(TestDominantAxesError);
  MITK_TEST(TestCheckRotationMatrix);

  // Currently commented out, see See bug 15990
  // MITK_TEST(testPlaneGeometryInitializeOrder);
  MITK_TEST(TestIntersectionPoint);
  MITK_TEST(TestCase1210);

  CPPUNIT_TEST_SUITE_END();

private:
  // private test members that are initialized by setUp()
  mitk::PlaneGeometry::Pointer planegeometry;
  mitk::Point3D origin;
  mitk::Vector3D right, bottom, normal, spacing;
  mitk::ScalarType width, height;
  mitk::ScalarType widthInMM, heightInMM, thicknessInMM;

public:
  void setUp() override
  {
    planegeometry = mitk::PlaneGeometry::New();
    width = 100;
    widthInMM = width;
    height = 200;
    heightInMM = height;
    thicknessInMM = 1.0;
    mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
    mitk::FillVector3D(right, widthInMM, 0, 0);
    mitk::FillVector3D(bottom, 0, heightInMM, 0);
    mitk::FillVector3D(normal, 0, 0, thicknessInMM);
    mitk::FillVector3D(spacing, 1.0, 1.0, thicknessInMM);

    planegeometry->InitializeStandardPlane(right, bottom);
    planegeometry->SetOrigin(origin);
    planegeometry->SetSpacing(spacing);
  }

  void tearDown() override {}
  // This test verifies inheritance behaviour, this test will fail if the behaviour changes in the future
  void TestInheritance()
  {
    mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New();
    mitk::Geometry3D::Pointer g3d = dynamic_cast<mitk::Geometry3D *>(plane.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("Planegeometry should not be castable to Geometry 3D", g3d.IsNull());

    mitk::BaseGeometry::Pointer base = dynamic_cast<mitk::BaseGeometry *>(plane.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("Planegeometry should be castable to BaseGeometry", base.IsNotNull());

    g3d = mitk::Geometry3D::New();
    base = dynamic_cast<mitk::BaseGeometry *>(g3d.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("Geometry3D should be castable to BaseGeometry", base.IsNotNull());

    mitk::SlicedGeometry3D::Pointer sliced = mitk::SlicedGeometry3D::New();
    g3d = dynamic_cast<mitk::Geometry3D *>(sliced.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("SlicedGeometry3D should not be castable to Geometry3D", g3d.IsNull());

    mitk::ThinPlateSplineCurvedGeometry::Pointer thin = mitk::ThinPlateSplineCurvedGeometry::New();
    plane = dynamic_cast<mitk::PlaneGeometry *>(thin.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("AbstractTransformGeometry should be castable to PlaneGeometry", plane.IsNotNull());

    plane = mitk::PlaneGeometry::New();
    mitk::AbstractTransformGeometry::Pointer atg = dynamic_cast<mitk::AbstractTransformGeometry *>(plane.GetPointer());
    CPPUNIT_ASSERT_MESSAGE("PlaneGeometry should not be castable to AbstractTransofrmGeometry", atg.IsNull());
  }

  void TestDominantAxesError()
  {
    auto image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("NotQuiteARotationMatrix.nrrd"));
    auto matrix = image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().transpose();
    std::vector< int > axes = mitk::PlaneGeometry::CalculateDominantAxes(matrix);
    CPPUNIT_ASSERT_MESSAGE("Domiant axes cannot be determined in this dataset. Output should be default ordering.", axes.at(0)==0 && axes.at(1)==1 && axes.at(2)==2);
  }

  void TestCheckRotationMatrix()
  {
    auto image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("NotQuiteARotationMatrix.nrrd"));
    bool is_rotation = mitk::PlaneGeometry::CheckRotationMatrix(image->GetGeometry()->GetIndexToWorldTransform(), 1e-8);
    CPPUNIT_ASSERT_MESSAGE("Since the test data matrix is not quite a rotation matrix, this should be detected.", !is_rotation);
  }

  void TestLefthandedCoordinateSystem()
  {
    /**
     * @brief This method tests InitializeStandardPlane() and IndexToWorld()
     * with a left-handed coordinate orientation or indexToWorldMatrix.
     *
     * Of course this test does not use standard Parameters, which are right-handed.
     * See also discussion of bug #11477: http://bugs.mitk.org/show_bug.cgi?id=11477
     */
    planegeometry = mitk::PlaneGeometry::New();
    width = 100;
    widthInMM = 5;
    height = 200;
{'fraction_non_alphanumeric': 0.14034165571616294, 'fraction_numerical': 0.015243101182654402, 'mean_word_length': 5.889559444779723, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7547180', 'n_tokens_mistral': 3774, 'n_tokens_neox': 3593, 'n_words': 762}