• Save
VTK
Upcoming SlideShare
Loading in...5
×
 

VTK

on

  • 1,150 views

 

Statistics

Views

Total Views
1,150
Views on SlideShare
1,149
Embed Views
1

Actions

Likes
1
Downloads
0
Comments
0

1 Embed 1

http://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

VTK VTK Presentation Transcript

  • 2012-11-10김명관/아꿈사
  • OsiriXOpen-Source Architecture
  • Visualization Toolkit (VTK)데이터 프로세싱과 시각화를 위한 시스템활용분야 scientific computing medical image analysis computational geometry rendering image processing
  • 개발 배경초기 개발자들은 GE Corporate R&D의 연구원LYMB에서 많은 영향을 받음 C언어로 스몰토크와 같은 환경을 구성
  • 장애물지적재산권 GE외부에 소스를 제공 할 수 없음비 표준, 독점소프트웨어 고객들이 배우기 꺼림 표준 툴 셋의 지원을 받을 수 없음
  • 오픈라이선스가장 중요한 디자인적 결정개방표준, 협업플랫폼 개발현재 Kitware를 통해 서비스 및 컨설팅
  • VTK?초기컨셉 과학데이터 시각화시스템시각화시스템 ≠ 렌더링 시각뿐 아니라 촉각, 청각, 기타 모든 형태시각화의 대상 ≠ 기하학, 위상 스칼라(온도, 압력...), 벡터(속도...), tensors(stress and strain) 등등현재 과학시각화(시공간정보의 표현) 정보시각화(보다 추상적인 데이터) 인구통계, 웹페이지, 문서, 테이블, 그래프, 트리 등등
  • 시각화 시스템으로서 VTK의 역할데이터를 얻고, 인간의 감각이 받아들일 수 있는 형태로 변환핵심 역할은 데이터 흐름 파이프라인을 만들어 내는 것 ingesting → processing → representing → rendering
  • Hybrid wrapper facility자동으로 다른 언어 바인딩을 생성Python, Java, Tcl을 지원다른 언어도 추가 가능컴파일러, 인터프리터를 목적에 맞게 선택 고성능이 필요한 부분은 컴파일러 프로토타이핑을 위해 인터프리텅
  • 개발툴빌드설정 – CMake테스트 – CDash/CTest크로스플랫폼 배포 – CPack VTK는 슈퍼컴퓨터를 포함한 거의 모든 컴퓨터에서 빌드 가능웹페이지, 위키, 메일링리스트문서화 – Doxygen이슈관리 - Mantis
  • 특징VTK는 객체지향시스템일반적으로 모든 데이터 맴버는 protected 또는 privateSet, Get 매소드를 이용해 접근Set, Get 매소드는 매크로 이용해 만들어 짐 vtkSetMacro(Tolerance,double); vtkGetMacro(Tolerance,double); virtual void SetTolerance(double); virtual double GetTolerance();
  • #define vtkSetMacro(name,type) virtual void Set##name (type _arg) { vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting " #name " to " << _arg); if (this->name != _arg) { this->name = _arg; this->Modified(); } }#define vtkGetMacro(name,type) virtual type Get##name () { vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " of " << this->name ); return this->name; }
  • PIMPL 디자인 패턴성능적인 이유로 템플릿을 널리 사용public class API에서는 템플릿이 보이지 않음템플릿 사용으로 인한 복잡도를 유저 또는 애플리케이션 개발자에게 감춤
  • 래퍼런스 카운트vtkObject의 서브클래스인 VTK의 대부분의 클래스는 레퍼런스 카운트 능력을 가지고 있다.가비지 콜렉션이 아닌 래퍼런스 카운트를 선택한 이유 데이터가 매우 클 수 있으므로 VTK는 데이터 삭제에 대한 완벽한 제어가 필요 예를 들어 1000x1000x1000 인 바이트 데이터 볼륨의 크기는 기가바이트 얕은복사
  • vtkCamera *camera = vtkCamera::New();//reference count is 1camera->Register(this);//reference count is 2camera->Unregister(this);//reference count is 1renderer->SetActiveCamera(camera);//reference count is 2renderer->Delete();//ref count is 1 when renderer is deletedcamera->Delete();//camera self destructs
  • Reference cyclesvtkGarbageCollector 사이클에 관련된 객체를 관리 레퍼런스 카운트 관계의 위상분석을 통해 레퍼 런스 사이클을 찾아내고 삭제
  • 팩토리대부분의 인스턴스는 정적 멤버로 구현된 개체 팩토리를 이용vtkLight *a = vtkLight::New();여기서 중요한 것은 생성된 a가 vtkLight의 하위클래스일 뿐 정확히 무엇인지 모름중요한 것은 어플리케이션 이식가능성과 장치 독립성vtk초기에는 다양한 옵션이 있었다. gl, PHIGS, Starbase, XGL, and OpenGL이들 대부분은 사라졌지만 새롭게 DirectX와 GPU기반의 접근이 포함되었다.vtk로 작성된 어플리케이션 개발자가 새로운 기술을 지원하는vtkLight 파생클래스로 변경한적 없다.
  • 데이터의 표현다양한 데이터를 표현 할 수 있는 것은 VTK의 강점 중 하나vtkDataObject 모든 데이터폼의 부모 시각화 파이프라인에서 처리 될 수 있다.
  • 파이프라인 아키텍쳐vtkDataObjectvtkAlgorithmvtkExecutive
  • 컨셉은 단순하지만 구현은 어려웠다.데이터 객체 데이터가 복잡 계층적이거나 그룹화된 데이터 병렬처리 데이터 파티셔닝, 일관성알고리즘 객체 입력 값은 불변실행 객체 재계산 감소를 위해 중간 결과를 캐쉬 데이터 셋이 매우 클 수 있으므로 빠른해제 가 필요
  • demand drivenwriter, mapper이 데이터를 필요로 할 때 적절한 데이터가 있다면 즉시 반환 적절한 데이터가 없으면 계산vtkPExodusIIReader *reader = vtkPExodusIIReader::New();reader->SetFileName("exampleFile.exo");vtkContourFilter *cont = vtkContourFilter::New();cont->SetInputConnection(reader->GetOutputPort());cont->SetNumberOfContours(1);cont->SetValue(0, 200);vtkQuadricDecimation *deci = vtkQuadricDecimation::New();deci->SetInputConnection(cont->GetOutputPort());deci->SetTargetReduction( 0.75 );vtkXMLPolyDataWriter *writer = vtkXMLPolyDataWriter::New();writer->SetInputConnection(deci->GetOuputPort());writer->SetFileName("outputFile.vtp");writer->Write();
  • Cache소스를 읽거나, 필터 실행결과를 캐시연산, 메모리 I/O 최소화데이터 객체 뿐 아니라 메타데이터를 포함
  • vtkPExodusIIReader *reader = vtkPExodusIIReader::New();reader->SetFileName("exampleFile.exo");vtkContourFilter *cont = vtkContourFilter::New();cont->SetInputConnection(reader->GetOutputPort());cont->SetNumberOfContours(1);cont->SetValue(0, 200);vtkQuadricDecimation *deci = vtkQuadricDecimation::New();deci->SetInputConnection(cont->GetOutputPort());deci->SetTargetReduction( 0.75 );vtkXMLPolyDataWriter *writer = vtkXMLPolyDataWriter::New();writer->SetInputConnection(deci->GetOuputPort());writer->SetFileName("outputFile.vtp");writer->Write();vtkXMLPolyDataWriter *writer2 = vtkXMLPolyDataWriter::New();writer2->SetInputConnection(deci->GetOuputPort());writer2->SetFileName("outputFile2.vtp");writer2->Write();
  • vtkPExodusIIReader *reader = vtkPExodusIIReader::New();reader->SetFileName("exampleFile.exo");vtkContourFilter *cont = vtkContourFilter::New();cont->SetInputConnection(reader->GetOutputPort());cont->SetNumberOfContours(1);cont->SetValue(0, 200);vtkQuadricDecimation *deci = vtkQuadricDecimation::New();deci->SetInputConnection(cont->GetOutputPort());deci->SetTargetReduction( 0.75 );vtkXMLPolyDataWriter *writer = vtkXMLPolyDataWriter::New();writer->SetInputConnection(deci->GetOuputPort());writer->SetFileName("outputFile.vtp");writer->Write();cont->SetValue(0, 400);vtkXMLPolyDataWriter *writer2 = vtkXMLPolyDataWriter::New();writer2->SetInputConnection(deci->GetOuputPort());writer2->SetFileName("outputFile2.vtp");writer2->Write();
  • 렌더링 서브시스템객체지향 렌더링 모델 vtkactor vtkRenderer vtkCamera vtkRenderWindow vtkLight vtkTransform vtkProperty vtkMapper
  • vtkOBJReader *reader = vtkOBJReader::New();reader->SetFileName("exampleFile.obj");vtkTriangleFilter *tri = vtkTriangleFilter::New();tri->SetInputConnection(reader->GetOutputPort());vtkQuadricDecimation *deci = vtkQuadricDecimation::New();deci->SetInputConnection(tri->GetOutputPort());deci->SetTargetReduction( 0.75 );vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();mapper->SetInputConnection(deci->GetOutputPort());vtkActor *actor = vtkActor::New();actor->SetMapper(mapper);vtkRenderer *renderer = vtkRenderer::New();renderer->AddActor(actor);vtkRenderWindow *renWin = vtkRenderWindow::New();renWin->AddRenderer(renderer);vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New();interactor->SetRenderWindow(renWin);renWin->Render();
  • 이벤트와 인터렉션 옵저버, 커맨더 디자인패턴 vtkObject는 옵저버들을 가질 수 있음class vtkProgressCommand : public vtkCommand{ public: static vtkProgressCommand *New() { return new vtkProgressCommand; } virtual void Execute(vtkObject *caller, unsigned long, void *callData) { double progress = *(static_cast<double*>(callData)); std::cout << "Progress at " << progress<< std::endl; }};vtkCommand* pobserver = vtkProgressCommand::New();vtkDecimatePro *deci = vtkDecimatePro::New();deci->SetInputConnection( byu->GetOutputPort() );deci->SetTargetReduction( 0.75 );deci->AddObserver( vtkCommand::ProgressEvent, pobserver );
  • 라이브러리 개요약 150만 라인 (주석포함, 자동생성코드 제외)약 1000 개의 C++ 클래스Rendering rendering, picking, image viewing, and interactionVolumeRendering volume rendering techniquesGraphics 3D geometry processingGenericFiltering non-linear 3D geometry processingImaging imaging pipelineHybrid classes requiring both graphics and imaging functionalityWidgets sophisticated interactionIO VTK input and outputInfovis information visualizationParallel parallel processing (controllers and communicators)Wrapping support for Tcl, Python, and Java wrappingExamples extensive, well-documented examples
  • VTK는 매우 성공한 시스템1993년 코드를 작성한 이래 지속적으로 성장개발 속도가 증가
  • 성장 할 수 있는 이유새로운 알고리즘과 기능의 지속적인 추가 인포매틱스, 차트, 렌더링등을 추가 새로운 과학 데이터셋 지원 3D인터렉션 GPU기반 렌더링, 데이터 처리사용자들과 커뮤니티를 통한 발전 ParaView : 과학시각화 응용프로그램 3D Slicer : 의공학 컴퓨팅 플랫폼개발프로세스의 발전 CMake, CDash, CTest, CPack Git
  • 성장의 관리커뮤니티와 소프트웨어의 성장을 관리하는것이 단기 목표 체계적인 관리 구조 모듈화
  • 기술적인 추가 사항데이터 프로세싱 파이프라인 리팩토링데이터와 상호작용 강화계산화학 관련 기능 추가새로운 렌더링 기술 지원새로운 형태의 데이터 세트 지원
  • 교훈디자인 모듈화 지나치게 높은 수준으로 너무 복잡한 클래스를 만들었다.C++ iterator 대부분의 경우 포트란 방식으로 선회 iterator를 널리 사용했다면 보다 유연했을 것이다.디자인 문제 렌더링 시스템이 너무 복잡하고 확장하기 어렵다. 초기 읽기전용 시각화 시스템으로 보았기에 데이터 편집 하기 어려운 구조이다.
  • -끝-
  • 책 내용이 끝났고…발표는 계속 됩니다.
  • 지금까지 나온 패턴들을 정리하겠습니다.할까 생각 했는데…다들 아는 이야기 지루할 것 같고VTK의 코드를 살펴보겠습니다.
  • 매크로를 이용한 타입정보class VTK_COMMON_EXPORT vtkObject : public vtkObjectBase{public: vtkTypeMacro(vtkObject,vtkObjectBase); …}
  • #define vtkTypeMacro(thisClass,superclass) typedef superclass Superclass; private: virtual const char* GetClassNameInternal() const { return #thisClass; } public: static int IsTypeOf(const char *type) { if ( !strcmp(#thisClass,type) ) { return 1; } return superclass::IsTypeOf(type); } virtual int IsA(const char *type) { return this->thisClass::IsTypeOf(type); } static thisClass* SafeDownCast(vtkObjectBase *o) { if ( o && o->IsA(#thisClass) ) { return static_cast<thisClass *>(o); } return NULL; } protected: virtual vtkObjectBase *NewInstanceInternal() const { return thisClass::New(); } public: thisClass *NewInstance() const { return thisClass::SafeDownCast(this->NewInstanceInternal()); }
  • 팩토리// vtkCone.hclass VTK_FILTERING_EXPORT vtkCone : public vtkImplicitFunction{public: static vtkCone *New(); ….}// vtkCone.cxx#include "vtkObjectFactory.h"vtkStandardNewMacro(vtkCone);
  • // vtkSetGet.h#define vtkStandardNewMacro(thisClass) thisClass* thisClass::New() { vtkObject* ret = vtkObjectFactory::CreateInstance(#thisClass); if(ret) { return static_cast<thisClass*>(ret); } return new thisClass; } vtkInstantiatorNewMacro(thisClass)#define vtkInstantiatorNewMacro(thisClass) extern vtkObject* vtkInstantiator##thisClass##New(); vtkObject* vtkInstantiator##thisClass##New() { return thisClass::New(); }
  • PIMPL// vtkArrayData.hclass VTK_FILTERING_EXPORT vtkArrayData : public vtkDataObject{ ...private: class implementation; implementation* const Implementation;};
  • // vtkArrayData.cxxclass vtkArrayData::implementation{public: std::vector<vtkArray*> Arrays;};vtkArrayData::vtkArrayData() : Implementation(new implementation()){}vtkArrayData::~vtkArrayData(){ this->ClearArrays(); delete this->Implementation;}
  • Command / Observerclass vtkProgressCommand : public vtkCommand{ public: static vtkProgressCommand *New() { return new vtkProgressCommand; } virtual void Execute(vtkObject *caller, unsigned long, void *callData) { double progress = *(static_cast<double*>(callData)); std::cout << "Progress at " << progress<< std::endl; }};vtkCommand* pobserver = vtkProgressCommand::New();vtkDecimatePro *deci = vtkDecimatePro::New();deci->SetInputConnection( byu->GetOutputPort() );deci->SetTargetReduction( 0.75 );deci->AddObserver( vtkCommand::ProgressEvent, pobserver );
  • // vtkObject.hclass VTK_COMMON_EXPORT vtkObject : public vtkObjectBase{ ….. vtkSubjectHelper *SubjectHelper; // List of observers on this object}// vtkObject.cxxunsigned long vtkObject::AddObserver(unsigned long event, vtkCommand *cmd, float p){ if (!this->SubjectHelper) { this->SubjectHelper = new vtkSubjectHelper; } return this->SubjectHelper->AddObserver(event,cmd, p);}unsigned long vtkSubjectHelper::AddObserver(unsigned long event, vtkCommand *cmd, float p){ vtkObserver *elem; // initialize the new observer element elem = new vtkObserver; elem->Priority = p; elem->Next = NULL; elem->Event = event; elem->Command = cmd; cmd->Register(0); elem->Tag = this->Count; this->Count++;….
  • void vtkObject::Modified(){ this->MTime.Modified(); this->InvokeEvent(vtkCommand::ModifiedEvent,NULL);}int vtkObject::InvokeEvent(unsigned long event, void *callData){ if (this->SubjectHelper) { return this->SubjectHelper->InvokeEvent(event,callData, this); } return 0;}
  • int vtkSubjectHelper::InvokeEvent(unsigned long event, void *callData, vtkObject *self){ …… elem = this->Start; vtkObserver *next; while (elem) { // store the next pointer because elem could disappear due to Command next = elem->Next; VisitedMapType::iterator vIter = visited.find(elem->Tag); if ((vIter != visited.end()) && (vIter->second == false) && elem->Command->GetPassiveObserver() && (elem->Event == event || elem->Event == vtkCommand::AnyEvent)) { vIter->second = true; vtkCommand* command = elem->Command; command->Register(command); elem->Command->Execute(self,event,callData); command->UnRegister(); } ……}
  • 가비지 콜렉션객체 생성시 콜스택 vtkGarbageCollector::TakeReference(vtkObjectBase * obj=0x003bb0e8) vtkObjectBaseToGarbageCollectorFriendship::TakeReference(vtkObjectBase * obj=0x003bb0e8) vtkObjectBase::RegisterInternal(vtkObjectBase * __formal=0x003b5248, int check=1) vtkObject::RegisterInternal(vtkObjectBase * o=0x003b5248, int check=1) vtkInformation::Register(vtkObjectBase * o=0x003b5248) vtkAlgorithm::vtkAlgorithm() vtkPolyDataAlgorithm::vtkPolyDataAlgorithm() vtkConeSource::vtkConeSource(int res=6) vtkConeSource::New()객체 삭제시 콜스택 vtkGarbageCollector::Collect(vtkObjectBase * root=0x003bb0e8) vtkObjectBase::UnRegisterInternal(vtkObjectBase * __formal=0x00000000, int check=1) vtkObject::UnRegisterInternal(vtkObjectBase * o=0x00000000, int check=1) vtkInformation::UnRegister(vtkObjectBase * o=0x00000000) vtkObjectBase::Delete() vtkAlgorithm::vtkAlgorithm() vtkPolyDataAlgorithm::vtkPolyDataAlgorithm() vtkConeSource::vtkConeSource(int res=6)
  • void vtkGarbageCollectorImpl::CollectInternal(vtkObjectBase* root){ // Identify strong components. this->FindComponents(root); // Delete all the leaked components. while(!this->LeakedComponents.empty()) { // Get the next leaked component. ComponentType* c = this->LeakedComponents.front(); this->LeakedComponents.pop(); // Subtract this components references to other components. This // may cause others to be queued. this->SubtractExternalReferences(c); // Collect the members of this component. this->CollectComponent(c); // We are done with this component. delete c; }#ifndef NDEBUG // Print remaining referenced components for debugging. for(ComponentsType::iterator i = this->ReferencedComponents.begin(), iend = this->ReferencedComponents.end(); i != iend; ++i) { this->PrintComponent(*i); }#endif // Flush remaining references owned by entries in referenced // components. for(ComponentsType::iterator c = this->ReferencedComponents.begin(), cend = this->ReferencedComponents.end(); c != cend; ++c) { for(ComponentType::iterator j = (*c)->begin(), jend = (*c)->end(); j != jend; ++j) { this->FlushEntryReferences(*j); } }}
  • -끝- special thanks to