diff --git a/code/masks/rttbMaskBoost.cpp b/code/masks/rttbMaskBoost.cpp deleted file mode 100644 index 8a81633..0000000 --- a/code/masks/rttbMaskBoost.cpp +++ /dev/null @@ -1,260 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "rttbMaskBoost.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidParameterException.h" - -namespace rttb{ - namespace masks{ - MaskBoost::MaskBoost(MaskBoost::GeometricInfoPtr aDoseGeoInfo, MaskBoost::StrPtr aStructure) - :_geometricInfo(aDoseGeoInfo), _structure(aStructure), _voxelInStructure(boost::make_shared()){ - - - if(! _geometricInfo ){ - throw rttb::core::NullPointerException("Error: Geometric info is NULL!"); - } - else if(!_structure){ - throw rttb::core::NullPointerException("Error: Structure is NULL!"); - } - - if(hasSelfIntersections()){ - throw rttb::core::InvalidParameterException("Error: structure has self intersections!"); - } - - - for(unsigned int i=0; i< aDoseGeoInfo->getNumSlices(); i++){ - std::vector voxelList = getBoundingBox(i); - rttb::VoxelGridIndex3D gridIndex3D0 = voxelList.at(0); - rttb::VoxelGridIndex3D gridIndex3D1 = voxelList.at(1); - - - for(unsigned int indexX = gridIndex3D0[0] ; indexX <= gridIndex3D1[0]; indexX ++ ){ - for(unsigned int indexY = gridIndex3D0[1]; indexY <= gridIndex3D1[1]; indexY ++){ - rttb::VoxelGridIndex3D currentIndex; - currentIndex[0] = indexX; - currentIndex[1] = indexY; - currentIndex[2] = i; - - rttb::VoxelGridID gridID; - _geometricInfo->convert(currentIndex, gridID); - - std::deque polygons = getIntersections(currentIndex); - double intersectionArea = calcArea(polygons); - - double voxelSize = _geometricInfo->getSpacing()[0] * _geometricInfo->getSpacing()[1]; - - if(intersectionArea > 0) { - double volumeFraction = intersectionArea/voxelSize; - if(volumeFraction > 1 && (volumeFraction-1) <= 0.0001){ - volumeFraction = 1; - } - core::MaskVoxel maskVoxel = core::MaskVoxel(gridID, (volumeFraction)); - _voxelInStructure->push_back(maskVoxel);//push back the mask voxel in structure - } - } - } - } - - sort(_voxelInStructure->begin(), _voxelInStructure->end()); - - } - - bool MaskBoost::hasSelfIntersections(){ - bool hasSelfIntersection = false; - - for(unsigned int indexZ=0; indexZ< _geometricInfo->getNumSlices(); indexZ++){ - rttb::VoxelGridIndex3D currentIndex(0,0,indexZ); - - std::vector boostPolygons = getIntersectionSlicePolygons(currentIndex); - - for(unsigned int i =0; i intersection; - boost::geometry::intersection(boostPolygons.at(i), boostPolygons.at(j), intersection); - if(intersection.size()>0){ - hasSelfIntersection = true; - std::cout << "Has self intersection! Slice: "<< indexZ << ", polygon "< MaskBoost::getBoundingBox(unsigned int sliceNumber){ - if(sliceNumber<0 || sliceNumber >= _geometricInfo->getNumSlices()){ - throw rttb::core::InvalidParameterException(std::string("Error: slice number is invalid!")); - } - - rttb::VoxelGridIndex3D currentIndex(0,0,sliceNumber); - - std::vector boostPolygons = getIntersectionSlicePolygons(currentIndex); - - double xMin = 0; - double yMin = 0; - double xMax = 0; - double yMax = 0; - for(unsigned int i =0; i box; - boost::geometry::envelope(boostPolygons.at(i), box); - BoostPoint2D minPoint = box.min_corner(); - BoostPoint2D maxPoint = box.max_corner(); - if(i==0){ - xMin = minPoint.x(); - yMin = minPoint.y(); - xMax = maxPoint.x(); - yMax = maxPoint.y(); - } - xMin = std::min(xMin, minPoint.x()); - yMin = std::min(yMin, minPoint.y()); - xMax = std::max(xMax, maxPoint.x()); - yMax = std::max(yMax, maxPoint.y()); - } - - rttb::WorldCoordinate3D nullWorldCoord; - _geometricInfo->indexToWorldCoordinate(VoxelGridIndex3D(0,0,0),nullWorldCoord); - rttb::WorldCoordinate3D minWorldCoord(xMin, yMin, nullWorldCoord.z()); - rttb::WorldCoordinate3D maxWorldCoord(xMax, yMax, nullWorldCoord.z()); - - rttb::VoxelGridIndex3D index0; - rttb::VoxelGridIndex3D index1; - _geometricInfo->worldCoordinateToIndex(minWorldCoord, index0); - _geometricInfo->worldCoordinateToIndex(maxWorldCoord, index1); - - std::vector voxelList; - voxelList.push_back(index0); - voxelList.push_back(index1); - - return voxelList; - } - - - /*Get intersection polygons of the contour and a voxel polygon*/ - std::deque MaskBoost::getIntersections(const rttb::VoxelGridIndex3D& aVoxelIndex3D){ - std::deque polygonDeque; - - BoostRing2D voxelPolygon = get2DContour(aVoxelIndex3D); - boost::geometry::correct(voxelPolygon); - - std::vector contourVector = getIntersectionSlicePolygons(aVoxelIndex3D); - for(unsigned int i=0; i intersection; - boost::geometry::intersection(voxelPolygon, contour, intersection); - - polygonDeque.insert(polygonDeque.end(), intersection.begin(), intersection.end()); - } - - return polygonDeque; - } - - - /*Calculate the intersection area*/ - double MaskBoost::calcArea(std::deque aPolygonDeque){ - double area = 0; - for(unsigned int i=0; iconvert(aMaskVoxel.getVoxelGridID(), gridIndex3D); - return gridIndex3D; - } - - MaskBoost::MaskVoxelListPointer MaskBoost::getRelevantVoxelVector(){ - return _voxelInStructure; - } - - MaskBoost::BoostRing2D MaskBoost::convert(const rttb::PolygonType& aRTTBPolygon){ - MaskBoost::BoostRing2D polygon2D; - BoostPoint2D firstPoint; - for(unsigned int i=0; i MaskBoost::getIntersectionSlicePolygons(const rttb::VoxelGridIndex3D& aVoxelGrid3D){ - std::vector boostPolygonVector; - - rttb::PolygonSequenceType polygonSequence = _structure->getStructureVector(); - - for(unsigned int i=0; i0){ - double polygonZCoor = rttbPolygon.at(0)[2]; - rttb::WorldCoordinate3D polygonPoint(0,0, polygonZCoor); - rttb::VoxelGridIndex3D polygonPointIndex3D; - _geometricInfo->worldCoordinateToIndex(polygonPoint, polygonPointIndex3D); - - //if the z - if(aVoxelGrid3D[2] == polygonPointIndex3D[2]){ - boostPolygonVector.push_back(convert(rttbPolygon)); - } - } - } - - return boostPolygonVector; - } - - MaskBoost::BoostRing2D MaskBoost::get2DContour(const rttb::VoxelGridIndex3D& aVoxelGrid3D){ - MaskBoost::BoostRing2D polygon; - rttb::WorldCoordinate3D rttbPoint; - _geometricInfo->indexToWorldCoordinate(aVoxelGrid3D, rttbPoint); - - BoostPoint2D point1 (rttbPoint[0], rttbPoint[1]); - boost::geometry::append(polygon, point1); - - double xSpacing = _geometricInfo->getSpacing()[0]; - double ySpacing = _geometricInfo->getSpacing()[1]; - - BoostPoint2D point2(rttbPoint[0]+xSpacing, rttbPoint[1]); - boost::geometry::append(polygon, point2); - - BoostPoint2D point3(rttbPoint[0]+xSpacing, rttbPoint[1]+ySpacing); - boost::geometry::append(polygon, point3); - - BoostPoint2D point4(rttbPoint[0], rttbPoint[1]+ySpacing); - boost::geometry::append(polygon, point4); - - boost::geometry::append(polygon, point1); - - return polygon; - - } - } -} \ No newline at end of file diff --git a/code/masks/rttbMaskBoost.h b/code/masks/rttbMaskBoost.h deleted file mode 100644 index 297cc65..0000000 --- a/code/masks/rttbMaskBoost.h +++ /dev/null @@ -1,96 +0,0 @@ -// ----------------------------------------------------------------------- -// RTToolbox - DKFZ radiotherapy quantitative evaluation library -// -// Copyright (c) German Cancer Research Center (DKFZ), -// Software development for Integrated Diagnostics and Therapy (SIDT). -// ALL RIGHTS RESERVED. -// See rttbCopyright.txt or -// http://www.dkfz.de/en/sidt/projects/rttb/copyright.html -// -// 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. -// -//------------------------------------------------------------------------ -/*! -// @file -// @version $Revision: 707 $ (last changed revision) -// @date $Date: 2014-09-04 16:37:24 +0200 (Do, 04 Sep 2014) $ (last change date) -// @author $Author: floca $ (last changed by) -*/ - - -#ifndef __RT_MASK_BOOST_H -#define __RT_MASK_BOOST_H - -#include "rttbBaseType.h" -#include "rttbStructure.h" -#include "rttbGeometricInfo.h" -#include "rttbMaskVoxel.h" -#include "rttbMaskAccessorInterface.h" - -#include -#include -#include -#include - -namespace rttb{ - namespace masks{ - - class MaskBoost{ - - public: - typedef boost::shared_ptr GeometricInfoPtr; - typedef core::Structure::StructTypePointer StrPtr; - typedef core::MaskAccessorInterface::MaskVoxelList MaskVoxelList; - typedef core::MaskAccessorInterface::MaskVoxelListPointer MaskVoxelListPointer; - typedef boost::geometry::model::d2::point_xy BoostPoint2D; - typedef boost::geometry::model::polygon > BoostPolygon2D; - typedef boost::geometry::model::ring > BoostRing2D; - - MaskBoost(GeometricInfoPtr aDoseGeoInfo, StrPtr aStructure); - - MaskVoxelListPointer getRelevantVoxelVector(); - - private: - - GeometricInfoPtr _geometricInfo; - - StrPtr _structure; - - //vector of the MaskVoxel inside the structure - MaskVoxelListPointer _voxelInStructure; - - /* Check if the structure has self intersections*/ - bool hasSelfIntersections(); - - - /*Get the min/max voxel index of the bounding box of the polygon in the slice with sliceNumber*/ - std::vector getBoundingBox(unsigned int sliceNumber); - - - /*Get intersection polygons of the contour and a voxel polygon*/ - std::deque getIntersections(const rttb::VoxelGridIndex3D& aVoxelIndex3D); - - - /*Calculate the intersection area*/ - double calcArea(std::deque aPolygonDeque); - - VoxelGridIndex3D getGridIndex3D(const core::MaskVoxel& aMaskVoxel); - - - /*Convert RTTB polygon to boost polygon*/ - BoostRing2D convert(const rttb::PolygonType& aRTTBPolygon); - - /*Get the intersection slice of the voxel, return the polygons in the slice*/ - std::vector getIntersectionSlicePolygons(const rttb::VoxelGridIndex3D& aVoxelGrid3D); - - /*Get the voxel 2d contour polygon*/ - BoostRing2D get2DContour(const rttb::VoxelGridIndex3D& aVoxelGrid3D); - - }; - - } -} - -#endif \ No newline at end of file diff --git a/testing/masks/BoostMaskAccessorTest.cpp b/testing/masks/BoostMaskAccessorTest.cpp index aee0adf..a8c03cf 100644 --- a/testing/masks/BoostMaskAccessorTest.cpp +++ b/testing/masks/BoostMaskAccessorTest.cpp @@ -1,87 +1,130 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // 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. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 880 $ (last changed revision) // @date $Date: 2015-01-13 14:14:24 +0100 (Di, 13 Jan 2015) $ (last change date) // @author $Author: zhangl $ (last changed by) */ #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" -#include "rttbOTBMaskAccessor.h" #include "rttbMaskVoxel.h" #include "rttbNullPointerException.h" #include "rttbException.h" #include "../core/DummyStructure.h" #include "../core/DummyDoseAccessor.h" #include "rttbMaskVoxelListTester.h" #include "rttbMaskRectStructTester.h" #include "rttbBoostMask.h" +#include "rttbBoostMaskAccessor.h" namespace rttb { namespace testing { /*! @brief BoostMaskAccessorTest. 1) test constructors - 2) test updateMask (do relevant voxels match?) - 3) test valid/convert - 4) test getMaskAt - 5) other interface functions (simple getters) + 2) test getRelevantVoxelVector + 3) test getMaskAt */ int BoostMaskAccessorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; typedef core::Structure::StructTypePointer StructTypePointer; - typedef masks::OTBMaskAccessor::MaskVoxelListPointer MaskVoxelListPointer; - typedef masks::OTBMaskAccessor::MaskVoxelList MaskVoxelList; + typedef masks::BoostMaskAccessor::MaskVoxelListPointer MaskVoxelListPointer; + typedef masks::BoostMaskAccessor::MaskVoxelList MaskVoxelList; // generate test structure set boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DummyStructure myStructGenerator(spTestDoseAccessor->getGeometricInfo()); GridIndexType zPlane = 4; core::Structure myTestStruct = myStructGenerator.CreateRectangularStructureCentered(zPlane); StructTypePointer spMyStruct = boost::make_shared(myTestStruct); - - //test BoostMask constructor boost::shared_ptr geometricPtr = boost::make_shared(spTestDoseAccessor->getGeometricInfo()); - + //1) test BoostMask and BoostMaskAccessor constructor CHECK_NO_THROW( rttb::masks::BoostMask(geometricPtr, spMyStruct)); rttb::masks::BoostMask boostMask = rttb::masks::BoostMask(geometricPtr, spMyStruct); - + CHECK_NO_THROW(rttb::masks::BoostMaskAccessor(spMyStruct, geometricPtr)); + rttb::masks::BoostMaskAccessor boostMaskAccessor(spMyStruct, geometricPtr); //2) test getRelevantVoxelVector CHECK_NO_THROW(boostMask.getRelevantVoxelVector()); + CHECK_NO_THROW(boostMaskAccessor.getRelevantVoxelVector()); + + + //3) test getMaskAt + const VoxelGridIndex3D inMask1(2, 1, 4); //corner -> volumeFraction = 0.25 + const VoxelGridIndex3D inMask2(3, 4, 4); //inside ->volumeFraction = 1 + const VoxelGridIndex3D inMask3(4, 5, 4); //side -> volumeFraction = 0.5 + const VoxelGridIndex3D outMask1(7, 5, 4); + const VoxelGridIndex3D outMask2(2, 1, 2); + VoxelGridID testId; + double errorConstant = 1e-7; + + core::MaskVoxel tmpMV1(0), tmpMV2(0); + CHECK(boostMaskAccessor.getMaskAt(inMask1, tmpMV1)); + geometricPtr->convert(inMask1, testId); + CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); + CHECK_EQUAL(tmpMV1, tmpMV2); + CHECK_CLOSE(0.25, tmpMV1.getRelevantVolumeFraction(), errorConstant); + CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); + + CHECK(boostMaskAccessor.getMaskAt(inMask2, tmpMV1)); + CHECK(geometricPtr->convert(inMask2, testId)); + CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); + CHECK_EQUAL(tmpMV1, tmpMV2); + CHECK_EQUAL(1, tmpMV1.getRelevantVolumeFraction()); + CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); + + CHECK(boostMaskAccessor.getMaskAt(inMask3, tmpMV1)); + CHECK(geometricPtr->convert(inMask3, testId)); + CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); + CHECK_EQUAL(tmpMV1, tmpMV2); + CHECK_CLOSE(0.5, tmpMV1.getRelevantVolumeFraction(), errorConstant); + CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); + + CHECK(!boostMaskAccessor.getMaskAt(outMask1, tmpMV1)); + CHECK(geometricPtr->convert(outMask1, testId)); + CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); + CHECK_EQUAL(tmpMV1, tmpMV2); + CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); + //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask + + CHECK(!boostMaskAccessor.getMaskAt(outMask2, tmpMV1)); + CHECK(geometricPtr->convert(outMask2, testId)); + CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); + CHECK_EQUAL(tmpMV1, tmpMV2); + CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); + //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask - MaskVoxelListPointer voxelListBoost = boostMask.getRelevantVoxelVector(); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb