ROI Utilities 3D

1 개요

1.1 소개

3D 객체에 대해 ROI 영역을 설정할 수 있는 클래스입니다.

1.2 사용 사례

2 알고리즘 설명

2.1 Include

ROI 영역 내부의 정점들만 선택합니다. 기존의 선택 결과를 초기화하고 수행합니다.

Source 3D Object Result (Include)
Source Result
Fig. ROI Utilities 3D(Include) 동작 실행 결과

2.2 Exclude

ROI 영역을 제외한 나머지 부분을 선택합니다. 기존의 선택 결과를 초기화하고 수행합니다.

Source 3D Object Result (Exclude)
Source Result
Fig. ROI Utilities 3D(Exclude) 동작 실행 결과

2.3 Add

현재 선택된 정점을 유지한 상태에서 ROI 영역 안의 정점을 추가로 선택(합집합)합니다.

Source 3D Object Result (Add)
Source Result
Fig. ROI Utilities 3D(Add) 동작 실행 결과

2.4 Remove

현재 선택된 정점에서 ROI 영역 안의 정점을 선택 해제(차집합)합니다.

Source 3D Object Result (Remove)
Source Result
Fig. ROI Utilities 3D(Remove) 동작 실행 결과

2.5 XOR

현재 선택된 정점과 ROI 영역 안의 정점을 XOR 선택합니다. ROI 영역 안의 정점이 이미 기존에 선택된 정점일 경우 선택을 해제하고, 기존에 선택되지 않은 정점이 ROI 영역에 포함될 경우 해당 정점을 선택합니다.

Source 3D Object Result (XOR)
Source Result
Fig. ROI Utilities 3D(XOR) 동작 실행 결과

3 파라미터 설정 및 사용 방법

3.1 3D 객체(CFL3DObject) 추가하기

void PushBack3DObject(const FLImaging::Foundation::CFL3DObject* pObject3D);

3D 객체(CFL3DObject)를 추가합니다. 깊은 복사를 하지 않으며, CROIUtilities3D객체에서는 3D 객체에 대한 메모리 관리를 하지 않습니다.

3.2 ROI 추가하기

void PushBackROI(const Foundation::CFLFrustum3<float>& roi);
void PushBackROI(const Base::THexahedron<float>& roi);

3D ROI 객체를 깊은 복사하여 ROI를 추가합니다.

3.3 선택 유형 설정

const CResult SetSelectionType(EResultSelectionType eType = EResultSelectionType_Include);

ROI 연산 시 결과를 선택하는 방식을 지정합니다.

3.4 결과 얻어 오기

결과를 얻는 방식에는 배열로 결과를 얻는 방식과 3D 객체(CFL3DObject)로 결과를 얻는 방식이 있습니다.

배열로 얻기

const CResult GetResult(Base::CFLArray<Base::CFLArray<int32_t>>& fla2ResultSatisfiedIndex) const;

결과값은 추가한 3D Object 개수와 선택된 정점 개수로 이루어진 2차원 배열입니다. CROIUtilities3D 객체에 CFL3DObject 객체를 N개 추가(CROIUtilities3D::PushBack3DObject())했다면 총 N개의 배열이 되며, 각 배열 안에는 ROI 안에 포함된 정점의 인덱스가 들어 있습니다.

3D 객체(CFL3DObject)로 얻기

const CResult GetResult(Foundation::CFL3DObject* pResultObject3D) const;
const CResult GetResult(Foundation::CFL3DObject& resultObject3D) const;

추가한 3D Object에서 선택된 정점만을 추출하여 하나의 3D Object로 합쳐 반환합니다.

4 예제 코드

CResult res = EResult_UnknownError;

do
{
    // 3D 객체 선언 // Declare a 3D object
    CFL3DObject fl3DObjLeft, fl3DObjRight;
    // 3D 객체 로드 // Load a 3D object
    res = fl3DObjLeft.Load(L"../../ExampleImages/ROIUtilities3D/Left Cam.ply");
    res = fl3DObjRight.Load(L"../../ExampleImages/ROIUtilities3D/Right Cam.ply");
    
    // 절두체 ROI 선언 // Declare the frustum ROI
    CFLFrustum3<float> flfr;
    flfr.flqQuads[0].flpPoints[0] = TPoint3<float>(0.865622f, 0.020000f, 4.678259f);
    flfr.flqQuads[0].flpPoints[1] = TPoint3<float>(0.865622f, -0.827275f, 4.678259f);
    flfr.flqQuads[0].flpPoints[2] = TPoint3<float>(-0.016235f, -0.827275f, 4.678259f);
    flfr.flqQuads[0].flpPoints[3] = TPoint3<float>(-0.016235f, 0.020000f, 4.678259f);
    flfr.flqQuads[1].flpPoints[0] = TPoint3<float>(1.088763f, 0.020000f, -4.300266f);
    flfr.flqQuads[1].flpPoints[1] = TPoint3<float>(1.088763f, -2.042157f, -4.300266f);
    flfr.flqQuads[1].flpPoints[2] = TPoint3<float>(-1.057563f, -2.042157f, -4.300266f);
    flfr.flqQuads[1].flpPoints[3] = TPoint3<float>(-1.057563f, 0.020000f, -4.300266f);

    // CROIUtilities3D 객체 선언 // Declare the CROIUtilities3D object
    CROIUtilities3D roiUtil3D;

    // CROIUtilities3D 객체에 3D Object 추가 // Add 3D objects to the CROIUtilities3D object
    roiUtil3D.PushBack3DObject(&fl3DObjLeft);
    roiUtil3D.PushBack3DObject(&fl3DObjRight);

    // CROIUtilities3D 객체에 절두체 ROI 추가 // Add the frustum ROI to the CROIUtilities3D object
    roiUtil3D.PushBackROI(flfr);

    // 선택 타입 설정 : ROI 안에 포함되는 정점만 선택 // Set the selection type to include only vertices inside the ROI
    roiUtil3D.SetSelectionType(CROIUtilities3D::EResultSelectionType_Include);

    // CROIUtilities3D 실행 // Execute the CROIUtilities3D object
    if((res = roiUtil3D.Execute()).IsFail())
        break;

    // CROIUtilities3D 에서 결과 얻어 오기 // Retrieve the results from CROIUtilities3D
    CFLArray<CFLArray<int32_t>> flfaResultROIIndexInclude;
    if((res = roiUtil3D.GetResult(flfaResultROIIndexInclude)).IsFail())
        break;
    
    if(flfaResultROIIndexInclude.GetCount())
    {
        int32_t i32ObjectIdx = 0;

        // 3D 뷰어에 추가된 3D 객체의 개수 // Number of 3D objects added to the 3D viewer
        int32_t i32ObjectCount = roiUtil3D.Get3DObjectCount();

        for(int32_t i = 0; i < i32ObjectCount; ++i)
        {
            // i번째 3D 객체의 데이터(CFL3DObject) // Data of the i-th 3D object (CFL3DObject)
            CFL3DObject* pObjData = roiUtil3D.Get3DObject(i);

            // 해당 객체가 없다면 continue // Skip if the object data is null
            if(!pObjData)
                continue;

            // i번째 3D 객체에 대한 결과값 배열. 이 배열은 i번째 3D 객체에 대해, ROI 내부에 위치한 정점의 인덱스로 이루어짐 // Result array for the i-th 3D object. Contains indices of vertices within the ROI.
            CFLArray<int32_t>& flaCollisionIndex = flfaResultROIIndexInclude.GetAt(i32ObjectIdx);
            i32ObjectIdx++;

            if(flaCollisionIndex.IsEmpty())
                continue;

            int32_t i32CollisionIndexCount = (int32_t)flaCollisionIndex.GetCount();

            CFLArray<Base::TPoint3<uint8_t>>* pFlaVertexColor = (CFLArray<Base::TPoint3<uint8_t>>*)pObjData->GetVertexColors();

            // i번째 3D 객체에 대해, ROI 내부에 위치한 정점을 빨간색으로 표시 // Mark vertices within the ROI of the i-th 3D object in red
            for(int32_t j = 0; j < i32CollisionIndexCount; ++j)
                pFlaVertexColor->SetAt(flaCollisionIndex.GetAt(j), TPoint3<uint8_t>(255, 0, 0)); // RED
        }
    }
}
while(false);
CResult res;

do
{
	// 3D 객체 선언 // Declare a 3D object
	CFL3DObject fl3DObjLeft = new CFL3DObject();
	CFL3DObject fl3DObjRight = new CFL3DObject();

	// 3D 객체 로드 // Load a 3D object
	res = fl3DObjLeft.Load("../../ExampleImages/ROIUtilities3D/Left Cam.ply");
	res = fl3DObjRight.Load("../../ExampleImages/ROIUtilities3D/Right Cam.ply");

	// 절두체 ROI 선언 // Declare the frustum ROI
	CFLFrustum3<float> flfr = new CFLFrustum3<float>();
	flfr.flqQuads[0].flpPoints[0] = new CFLPoint3<float>(0.865622f, 0.020000f, 4.678259f);
	flfr.flqQuads[0].flpPoints[1] = new CFLPoint3<float>(0.865622f, -0.827275f, 4.678259f);
	flfr.flqQuads[0].flpPoints[2] = new CFLPoint3<float>(-0.016235f, -0.827275f, 4.678259f);
	flfr.flqQuads[0].flpPoints[3] = new CFLPoint3<float>(-0.016235f, 0.020000f, 4.678259f);
	flfr.flqQuads[1].flpPoints[0] = new CFLPoint3<float>(1.088763f, 0.020000f, -4.300266f);
	flfr.flqQuads[1].flpPoints[1] = new CFLPoint3<float>(1.088763f, -2.042157f, -4.300266f);
	flfr.flqQuads[1].flpPoints[2] = new CFLPoint3<float>(-1.057563f, -2.042157f, -4.300266f);
	flfr.flqQuads[1].flpPoints[3] = new CFLPoint3<float>(-1.057563f, 0.020000f, -4.300266f);

	// CROIUtilities3D 객체 선언 // Declare the CROIUtilities3D object
	CROIUtilities3D roiUtil3D = new CROIUtilities3D();

	// CROIUtilities3D 객체에 3D Object 추가 // Add 3D objects to the CROIUtilities3D object
	roiUtil3D.PushBack3DObject(fl3DObjLeft);
	roiUtil3D.PushBack3DObject(fl3DObjRight);

	// CROIUtilities3D 객체에 절두체 ROI 추가 // Add the frustum ROI to the CROIUtilities3D object
	roiUtil3D.PushBackROI(flfr);

	// 선택 타입 설정 : ROI 안에 포함되는 정점만 선택 // Set the selection type to include only vertices inside the ROI
	roiUtil3D.SetSelectionType(CROIUtilities3D.EResultSelectionType.Include);

	// CROIUtilities3D 실행 // Execute the CROIUtilities3D object
	if((res = roiUtil3D.Execute()).IsFail())
		break;

	// CROIUtilities3D 에서 결과 얻어 오기 // Retrieve the results from CROIUtilities3D
	List<List<int>> arr2ResultROIIndexInclude = new List<List<int>>();
	if((res = roiUtil3D.GetResult(ref arr2ResultROIIndexInclude)).IsFail())
		break;

	if(arr2ResultROIIndexInclude.Count() > 0)
	{
		int i32ObjectIdx = 0;

		// 3D 뷰어에 추가된 3D 객체의 개수 // Number of 3D objects added to the 3D viewer
		int i32ObjectCount = roiUtil3D.Get3DObjectCount();

		for(int i = 0; i < i32ObjectCount; ++i)
		{
			// i번째 3D 객체의 데이터(CFL3DObject) // Data of the i-th 3D object (CFL3DObject)
			CFL3DObject pObjData = roiUtil3D.Get3DObject(i);

			// 해당 객체가 없다면 continue // Skip if the object data is null
			if(pObjData == null)
				continue;

			// i번째 3D 객체에 대한 결과값 배열. 이 배열은 i번째 3D 객체에 대해, ROI 내부에 위치한 정점의 인덱스로 이루어짐 // Result array for the i-th 3D object. Contains indices of vertices within the ROI.
			List<int> flaCollisionIndex = arr2ResultROIIndexInclude[i32ObjectIdx];
			i32ObjectIdx++;

			if(flaCollisionIndex.Count() == 0)
				continue;

			int i32CollisionIndexCount = (int)flaCollisionIndex.Count();

			// i번째 3D 객체에 대해, ROI 내부에 위치한 정점을 빨간색으로 표시 // Mark vertices within the ROI of the i-th 3D object in red
			for(int j = 0; j < i32CollisionIndexCount; ++j)
				pObjData.SetVertexColorAt(flaCollisionIndex[j], 255, 0, 0); // RED
		}
	}
}
while(false);