1 /*=========================================================================
2 *
3 * Copyright Insight Software Consortium
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18
19 #include <iostream>
20 #include "itkAffineTransform.h"
21 #include "itkSimpleDataObjectDecorator.h"
22 #include "itkDataObjectDecorator.h"
23 #include "itkAutoPointerDataObjectDecorator.h"
24 #include "itkTestingMacros.h"
25
26 namespace {
27 template <typename CharType, typename TraitsType, typename MemberType, typename AllocatorType>
28 std::basic_ostream<CharType, TraitsType>&
operator <<(std::basic_ostream<CharType,TraitsType> & os,const std::vector<MemberType,AllocatorType> & p)29 operator<<(std::basic_ostream<CharType, TraitsType>&os, const std::vector<MemberType,AllocatorType> &p)
30 {
31 os << "vector<" << typeid(MemberType).name() << "> with " << p.size() << " elements " << std::endl;
32 return os;
33 }
34 }
35
itkDecoratorTest(int,char * [])36 int itkDecoratorTest(int, char* [] )
37 {
38 int status = 0;
39
40 std::cout << "----------------------------------------------------"
41 << std::endl;
42
43 using FloatObjectType = itk::SimpleDataObjectDecorator<float>;
44
45 FloatObjectType::Pointer f = FloatObjectType::New();
46 f->Set(5.0);
47
48 std::cout << "Value of f: " << f->Get() << std::endl;
49 std::cout << "FloatDataObject: " << f << std::endl;
50
51 std::cout << "----------------------------------------------------"
52 << std::endl;
53
54 using TransformType = itk::AffineTransform<double, 3>;
55 using TransformObjectType = itk::DataObjectDecorator<TransformType>;
56
57 TransformObjectType::Pointer decoratedTransform = TransformObjectType::New();
58 TransformType::Pointer transformObject = TransformType::New();
59 const TransformType * constTransformObject = transformObject;
60
61 transformObject->Scale( 5.0 );
62
63 decoratedTransform->Set( constTransformObject );
64
65 const itk::ModifiedTimeType t1 = decoratedTransform->GetMTime();
66 transformObject->Modified();
67 TEST_EXPECT_TRUE(t1 < decoratedTransform->GetMTime());
68
69 TransformObjectType::Pointer decoratedTransform2 = TransformObjectType::New();
70 decoratedTransform2->Graft( decoratedTransform );
71
72 TEST_EXPECT_EQUAL( decoratedTransform2->Get(), decoratedTransform->Get() );
73
74 const itk::ModifiedTimeType t2 = decoratedTransform->GetMTime();
75 decoratedTransform2->GetModifiable()->Modified();
76 TEST_EXPECT_TRUE(t2 < decoratedTransform->GetMTime());
77
78
79 std::cout << "Value of decoratedTransform: ";
80 decoratedTransform->Get()->Print(std::cout);
81 std::cout << "TransformDataObject: " << decoratedTransform;
82
83 using TransformBaseType = itk::Transform<double, 3>;
84 using TransformBaseObjectType = itk::DataObjectDecorator<TransformBaseType>;
85
86 TransformBaseObjectType::Pointer decoratedBaseTransform = TransformBaseObjectType::New();
87 //NOTE: GetPointer is needed to force selection of the correct overloaded function signature.
88 decoratedBaseTransform->Graft( decoratedTransform.GetPointer() );
89 TEST_EXPECT_TRUE( decoratedBaseTransform->Get() != nullptr );
90
91 decoratedBaseTransform->ReleaseData();
92 TEST_EXPECT_TRUE( decoratedBaseTransform->Get() == nullptr );
93 //NOTE: GetPointer is needed to force selection of the correct overloaded function signature.
94 decoratedBaseTransform->Graft( f.GetPointer() );
95 TEST_EXPECT_TRUE( decoratedBaseTransform->Get() == nullptr );
96
97 decoratedBaseTransform->Graft( static_cast<itk::DataObject *>(nullptr) );
98 //NOTE: GetPointer is needed to force selection of the correct overloaded function signature.
99 decoratedBaseTransform->Graft( decoratedTransform.GetPointer() );
100 TEST_EXPECT_TRUE( decoratedBaseTransform->Get() != nullptr );
101
102 decoratedBaseTransform->Graft( static_cast<itk::DataObject *>(nullptr) );
103 TEST_EXPECT_TRUE( decoratedBaseTransform->Get() != nullptr );
104
105 decoratedTransform->ReleaseData();
106 decoratedTransform->Graft( decoratedBaseTransform );
107 TEST_EXPECT_TRUE( decoratedTransform->Get() == nullptr );
108
109 std::cout << "----------------------------------------------------"
110 << std::endl;
111
112 using VectorType = std::vector<float>;
113 using VectorPointer = VectorType*;
114 using VectorObjectType = itk::SimpleDataObjectDecorator<VectorType>;
115 using VectorPointerObjectType = itk::AutoPointerDataObjectDecorator<VectorType>;
116
117 VectorType v;
118 v.resize(5);
119 std::cout << v << std::endl;
120 VectorObjectType::Pointer vo = VectorObjectType::New();
121 vo->Set(v);
122 std::cout << vo;
123 std::cout << "----------------------------------------------------"
124 << std::endl;
125
126 // The following code block will NOT cause a memory leak because the
127 // ownership of the dynamically allocated memory is passed to the
128 // AutoPointerDataObjectDecorator
129 {
130 VectorPointer vp;
131 vp = new VectorType;
132 vp->resize(3);
133 std::cout << *vp << std::endl;
134
135 VectorPointerObjectType::Pointer vop = VectorPointerObjectType::New();
136 vop->Set(vp);
137
138 std::cout << vop;
139 }
140
141 std::cout << "----------------------------------------------------"
142 << std::endl;
143
144 // The following code block will cause a memory leak because the
145 // decorator does not deallocate the memory that was passed in on a
146 // pointer. The AutoPointerDataObjectDecorator does delete the memory.
147 //using VectorPointerObjectType2 = itk::SimpleDataObjectDecorator<VectorPointer>;
148 //{
149 //VectorPointer vp2;
150 //vp2 = new VectorType;
151 //vp2->resize(4);
152 //std::cout << *vp2 << std::endl;
153
154 //VectorPointerObjectType2::Pointer vop2 = VectorPointerObjectType2::New();
155 //vop2->Set(vp2);
156
157 //std::cout << vop2;
158 //}
159
160 return status;
161 }
162