PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
LinearObjectBuffer.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 #include "PlusConfigure.h"
8 
9 #include "LinearObjectBuffer.h"
10 #include "igsioCommon.h"
11 
12 //-----------------------------------------------------------------------------
13 
15 {
16 }
17 
18 //-----------------------------------------------------------------------------
19 
21 {
22  for ( int i = 0; i < this->Size(); i++ )
23  {
24  delete this->objects.at(i);
25  }
26  this->objects.clear();
27 }
28 
29 //-----------------------------------------------------------------------------
30 
32 {
33  return this->objects.size();
34 }
35 
36 //-----------------------------------------------------------------------------
37 
39 {
40  return this->objects.at(index);
41 }
42 
43 //-----------------------------------------------------------------------------
44 
46 {
47  for ( int i = 0; i < this->Size(); i++ )
48  {
49  if ( STRCASECMP( this->GetLinearObject(i)->Name.c_str(), name.c_str() ) == 0 )
50  {
51  return this->GetLinearObject(i);
52  }
53  }
54 
55  LinearObject* obj = NULL;
56  return obj;
57 }
58 
59 //-----------------------------------------------------------------------------
60 
62 {
63  this->objects.push_back( newObject );
64 }
65 
66 //-----------------------------------------------------------------------------
67 
69 {
70  for ( int i = 0; i < catBuffer->Size(); i++ )
71  {
72  this->AddLinearObject( catBuffer->GetLinearObject(i) );
73  }
74 }
75 
76 //-----------------------------------------------------------------------------
77 
78 void LinearObjectBuffer::Translate( std::vector<double> vector )
79 {
80  for ( int i = 0; i < this->Size(); i++ )
81  {
82  this->GetLinearObject(i)->Translate( vector );
83  }
84 }
85 
86 //-----------------------------------------------------------------------------
87 
89 {
90  // Calculate the signature of everything in this, assume the inputted object is a buffer of references
91  for ( int i = 0; i < this->Size(); i++ )
92  {
93  std::vector<double> sig( refBuffer->Size(), 0.0 );
94  for ( int j = 0; j < refBuffer->Size(); j++ )
95  {
96  sig.at(j) = this->GetLinearObject(i)->DistanceToVector( refBuffer->GetLinearObject(j)->BasePoint );
97  }
98  this->GetLinearObject(i)->Signature = sig;
99  }
100 }
101 
102 //-----------------------------------------------------------------------------
103 
105 {
106  // For each object in this, find the object in candidates that has the closest signature
107  LinearObjectBuffer* matchedCandidates = new LinearObjectBuffer();
108  std::vector<LinearObject*> matchedObjects;
109  if ( this->Size() == 0 || candidates->Size() == 0 )
110  {
111  this->objects = matchedObjects;
112  return matchedCandidates;
113  }
114 
115  for ( int i = 0; i < this->Size(); i++ )
116  {
117 
118  LinearObject* closestObject = candidates->GetLinearObject(0);
119  double closestDistance = LinearObject::Norm( LinearObject::Subtract( this->GetLinearObject(i)->Signature, closestObject->Signature ) );
120 
121  for ( int j = 0; j < candidates->Size(); j++ )
122  {
123  if ( LinearObject::Norm( LinearObject::Subtract( this->GetLinearObject(i)->Signature, candidates->GetLinearObject(j)->Signature ) ) < closestDistance )
124  {
125  closestObject = candidates->GetLinearObject(j);
126  closestDistance = LinearObject::Norm( LinearObject::Subtract( this->GetLinearObject(i)->Signature, candidates->GetLinearObject(j)->Signature ) );
127  }
128  }
129 
130  // Only accept the matching if it is sufficiently good (this throws away potentially wrongly identified collected objects)
131  if ( closestDistance < matchingThreshold )
132  {
133  matchedObjects.push_back( this->GetLinearObject(i) );
134  matchedCandidates->AddLinearObject( closestObject );
135  }
136 
137  }
138 
139  this->objects = matchedObjects;
140 
141  return matchedCandidates;
142 }
143 
144 //-----------------------------------------------------------------------------
145 
147 {
148  const double CONDITION_THRESHOLD = 1e-3;
149 
150  // Assume each will take 3 rows. If it doesn't leaving them blank won't affect the result
151  vnl_matrix<double>* A = new vnl_matrix<double>( LinearObject::DIMENSION * this->Size(), LinearObject::DIMENSION, 0.0 );
152  vnl_matrix<double>* B = new vnl_matrix<double>( LinearObject::DIMENSION * this->Size(), 1, 0.0 );
153 
154  // We wish to solve the system A * X = B
155  for ( int i = 0; i < this->Size(); i++ )
156  {
157  int row = LinearObject::DIMENSION * i;
158  // A = I for point, B = coordinates
159  if ( strcmp( this->GetLinearObject(i)->Type.c_str(), "Point" ) == 0 )
160  {
161  Point* PointObject = (Point*) this->GetLinearObject(i);
162  A->put( row + 0, 0, 1.0 );
163  A->put( row + 1, 1, 1.0 );
164  A->put( row + 2, 2, 1.0 );
165  B->put( row + 0, 0, PointObject->BasePoint.at(0) );
166  B->put( row + 1, 0, PointObject->BasePoint.at(1) );
167  B->put( row + 2, 0, PointObject->BasePoint.at(2) );
168  }
169 
170  // A = Normal 1, Normal 2, B = Dot( Normal 1, BasePoint ), Dot( Normal 2, BasePoint )
171  if ( strcmp( this->GetLinearObject(i)->Type.c_str(), "Line" ) == 0 )
172  {
173  Line* LineObject = (Line*) this->GetLinearObject(i);
174  A->put( row + 0, 0, LineObject->GetOrthogonalNormal1().at(0) );
175  A->put( row + 0, 1, LineObject->GetOrthogonalNormal1().at(1) );
176  A->put( row + 0, 2, LineObject->GetOrthogonalNormal1().at(2) );
177  A->put( row + 1, 0, LineObject->GetOrthogonalNormal2().at(0) );
178  A->put( row + 1, 1, LineObject->GetOrthogonalNormal2().at(1) );
179  A->put( row + 1, 2, LineObject->GetOrthogonalNormal2().at(2) );
180  B->put( row + 0, 0, LinearObject::Dot( LineObject->GetOrthogonalNormal1(), LineObject->BasePoint ) );
181  B->put( row + 1, 0, LinearObject::Dot( LineObject->GetOrthogonalNormal2(), LineObject->BasePoint ) );
182  }
183 
184  // A = Normal, B = Dot( Normal, BasePoint )
185  if ( strcmp( this->GetLinearObject(i)->Type.c_str(), "Plane" ) == 0 )
186  {
187  Plane* PlaneObject = (Plane*) this->GetLinearObject(i);
188  A->put( row + 0, 0, PlaneObject->GetNormal().at(0) );
189  A->put( row + 0, 1, PlaneObject->GetNormal().at(1) );
190  A->put( row + 0, 2, PlaneObject->GetNormal().at(2) );
191  B->put( row + 0, 0, LinearObject::Dot( PlaneObject->GetNormal(), PlaneObject->BasePoint ) );
192  }
193 
194  }
195 
196  // Now, calculate X
197  vnl_matrix_inverse<double>* X = new vnl_matrix_inverse<double>( A->transpose() * (*A) );
198  if ( X->well_condition() < CONDITION_THRESHOLD ) // This is the inverse of the condition number
199  {
200  throw std::logic_error("Failed - centroid calculation is ill-conditioned!");
201  } // TODO: Error if ill-conditioned
202  vnl_matrix<double>* Y = new vnl_matrix<double>( X->inverse() * A->transpose() * (*B) );
203 
204  std::vector<double> centroid( LinearObject::DIMENSION, 0.0 );
205  centroid.at(0) = Y->get( 0, 0 );
206  centroid.at(1) = Y->get( 1, 0 );
207  centroid.at(2) = Y->get( 2, 0 );
208 
209  return centroid;
210 }
211 
212 //-----------------------------------------------------------------------------
213 
215 {
216  std::ostringstream xmlstring;
217 
218  xmlstring << "<Geometry>" << std::endl;
219  for ( int i = 0; i < this->Size(); i++ )
220  {
221  xmlstring << this->GetLinearObject(i)->ToXMLString();
222  }
223  xmlstring << "</Geometry>";
224 
225  return xmlstring.str();
226 }
227 
228 //-----------------------------------------------------------------------------
229 
230 void LinearObjectBuffer::FromXMLElement( vtkXMLDataElement* element )
231 {
232  LinearObject* blankObject = NULL;
233  this->objects = std::vector<LinearObject*>( 0, blankObject );
234 
235  int numElements = element->GetNumberOfNestedElements();
236 
237  for ( int i = 0; i < numElements; i++ )
238  {
239 
240  vtkXMLDataElement* noteElement = element->GetNestedElement( i );
241 
242  if ( STRCASECMP( noteElement->GetName(), "Reference" ) == 0 )
243  {
244  Reference* newObject = new Reference();
245  newObject->FromXMLElement( noteElement );
246  this->AddLinearObject( newObject );
247  }
248  if ( STRCASECMP( noteElement->GetName(), "Point" ) == 0 )
249  {
250  Point* newObject = new Point();
251  newObject->FromXMLElement( noteElement );
252  this->AddLinearObject( newObject );
253  }
254  if ( STRCASECMP( noteElement->GetName(), "Line" ) == 0 )
255  {
256  Line* newObject = new Line();
257  newObject->FromXMLElement( noteElement );
258  this->AddLinearObject( newObject );
259  }
260  if ( STRCASECMP( noteElement->GetName(), "Plane" ) == 0 )
261  {
262  Plane* newObject = new Plane();
263  newObject->FromXMLElement( noteElement );
264  this->AddLinearObject( newObject );
265  }
266  }
267 }
virtual void FromXMLElement(vtkXMLDataElement *element)
Definition: Plane.cxx:81
std::vector< double > CalculateCentroid()
void AddLinearObject(LinearObject *newObject)
void CalculateSignature(LinearObjectBuffer *refBuffer)
static double Norm(std::vector< double > vector)
virtual void FromXMLElement(vtkXMLDataElement *element)
Definition: Point.cxx:63
Definition: Line.h:17
virtual void FromXMLElement(vtkXMLDataElement *element)
Definition: Line.cxx:140
std::vector< double > BasePoint
Definition: LinearObject.h:23
void Translate(std::vector< double > vector)
for i
Definition: Point.h:18
void FromXMLElement(vtkXMLDataElement *element)
Definition: Plane.h:18
void Concatenate(LinearObjectBuffer *catBuffer)
std::vector< double > GetOrthogonalNormal2()
Definition: Line.cxx:93
static const int DIMENSION
Definition: LinearObject.h:25
virtual void FromXMLElement(vtkXMLDataElement *element)
Definition: Reference.cxx:65
static double Dot(std::vector< double > v1, std::vector< double > v2)
virtual std::string ToXMLString() const =0
LinearObject * GetLinearObject(int index) const
std::vector< double > Signature
Definition: LinearObject.h:22
virtual void Translate(std::vector< double > vector)=0
double DistanceToVector(std::vector< double > vector)
std::vector< double > GetOrthogonalNormal1()
Definition: Line.cxx:61
std::vector< double > GetNormal()
Definition: Plane.cxx:36
LinearObjectBuffer * GetMatches(LinearObjectBuffer *candidates, double matchingThreshold)
std::string ToXMLString() const
static std::vector< double > Subtract(std::vector< double > v1, std::vector< double > v2)
std::string Type
Definition: LinearObject.h:21