Page MenuHomePhabricator

EuclideanDistanceTo fails for the PlanarCross figure in the PlanarFigureIOTest
Closed, ResolvedPublic

Description

After fixing 4155 a new bug occured. The EuclideanDistanceTo test fails for the planar cross figure, because the original control point 0 is not equal to the received control point from the planar figure.
Added modified test case from T4155 as attachment.

Event Timeline

saruji added a subscriber: saruji.

modified PlanarFigureIOTest

The first problem was the given itk Vector. While using its normalize function it didn't check whether it would divide with 0.

const RealValueType norm = this->GetNorm();

  for( unsigned int i=0; i<TVectorDimension; i++) 
      {
      (*this)[i] = static_cast<T> (static_cast<RealValueType>((*this)[i]) / norm);
      }
}

After inserting a hack, which checked whether the value is 0 or not, all the tests passed.

But still all control points had exactly the same values in the output file. After consulting with Mathias Seitel, we figured out that the control points were chosen too big for the existing boundaries. That is the reason why every resulting value was cut to the same value (e.g. x=90 y=10 -> x=0.01 y=0.01 and x =20 y=20 -> x=0.01 y=0.01). So we chose significant small control points, which solved our problem (the original points were equal to the ones in the output file).

To fix this problem the user can either choose control points within the boundaries or change the existing boundaries.

In addition there should be a test to check the boundaries against the control points, so that other test cases won't fail because of the same problem.

(In reply to comment #4)

In addition there should be a test to check the boundaries against the control
points, so that other test cases won't fail because of the same problem.

Thanks a lot for looking into this. There is a test which checks if the control point boundary constraints work properly for PlanarCross in mitkPlanarCrossTest.cpp, method TestPlanarCrossPlacementConstrained(). Is that what you mean?

I looked into mitkPlanarCrossTest.cpp, method TestPlanarCrossPlacementConstrained(). And in this case the control point would be ok. But the problem is, there are additional constraints (we refered to them as "boundaries"), which are applied in mitkPlanarCross.cpp.

The method I'm refering to is mitk::PlanarCross::ApplyControlPointConstraints( unsigned int index, const Point2D& point ). If you follow it to mitk::Point2D mitk::PlanarFigure::ApplyControlPointConstraints( unsigned int index, const Point2D& point ) in the superclass mitkPlanarfigure.cpp, you will find the method m_Geometry2D->WorldToIndex( point, indexPoint ) and after that in mitkPlaneGeometry.cpp :

void PlaneGeometry::WorldToIndex( const Point2D &pt_mm, Point2D &pt_units ) const
{

pt_units[0]=pt_mm[0]*(1.0/m_ScaleFactorMMPerUnitX);
pt_units[1]=pt_mm[1]*(1.0/m_ScaleFactorMMPerUnitY);

if (m_ImageGeometry)
{
  pt_units[0]+=0.5;
  pt_units[1]+=0.5;
}

}

The problem here might be the scaling factor, because we went through the whole process with the Debugger and at this point the numbers (indexPoint parameter at WorldToIndex) get twisted into gibberish (e.g. 0.1335228) if you use normal control points like x=20 and y=20. Instead we tried x=0.002 and y=0.002 and the result was that the points where exactly the same after running the procedure.

I hope my comment isn't too confusing, but I tried to show the exact path we took to figure it out.

(In reply to comment #6)

But the problem is, there are additional constraints (we refered to them
as "boundaries"), which are applied in mitkPlanarCross.cpp.

You are right: the boundaries (or "bounds" as they are called in mitk::Geometry3D) define the cube described by the 3D Geometry in index coordinates (units). For a PlaneGeometry (which is derived from mitk::Geometry3D), this reduces to 2D, so the bounds give spatial extents of the plane, but in index coordinates (units), not in world coordinates (mm).

The methods WorldToIndex() and IndexToWorld() convert between both spaces, i.e. between unit and world coordinates. The ratio used to convert from world to unit coordinates directly derives from the "spacing" defined for the Geometry. Spacing can be different in x, y and z dimensions.

In the patch attached at to this bug, a PlaneGeometry is created which has quite small bounds (1.123456 in x and y) and even smaller spacing (0.0123456 in x and y).

The control points of PlanarFigures are specified in world coordinates, so in order to constrain them to the plane extents, the bounds of the plane converted into world coordinates space (mm) have to be used (by multiplying units bounds with spacing).

In PlanarCrossTest, the spacing of the plane equals 1.0, which is why world and index coordinates are equal. The method TestPlanarCrossPlacementConstrained() checks if points placed outside of the plane bounds (e.g. x= -20, or y = +120, while the plane has bounds of [0, 100] in both dimensions) are constrained properly (to x = 0 and y = 100 in the example).

So in your case, everything seems to have worked correctly, but due to the extremely small bounds of the defined plane, all control points were lying right of or above the plane, and therefore were all constrained to the exact same point.

Is this bug resolved? No failed tests on my system!

Merging "applicazion modules" component with "ExtApp plugins"