1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkIdList.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkIdList.h"
16 #include "vtkSMPTools.h" //for parallel sort
17 #include "vtkObjectFactory.h"
18 
19 vtkStandardNewMacro(vtkIdList);
20 
21 //----------------------------------------------------------------------------
vtkIdList()22 vtkIdList::vtkIdList()
23 {
24   this->NumberOfIds = 0;
25   this->Size = 0;
26   this->Ids = nullptr;
27 }
28 
29 //----------------------------------------------------------------------------
~vtkIdList()30 vtkIdList::~vtkIdList()
31 {
32   delete [] this->Ids;
33 }
34 
35 //----------------------------------------------------------------------------
Initialize()36 void vtkIdList::Initialize()
37 {
38   delete [] this->Ids;
39   this->Ids = nullptr;
40   this->NumberOfIds = 0;
41   this->Size = 0;
42 }
43 
44 //----------------------------------------------------------------------------
Allocate(const vtkIdType sz,const int vtkNotUsed (strategy))45 int vtkIdList::Allocate(const vtkIdType sz, const int vtkNotUsed(strategy))
46 {
47   if ( sz > this->Size)
48   {
49     this->Initialize();
50     this->Size = ( sz > 0 ? sz : 1);
51     if ( (this->Ids = new vtkIdType[this->Size]) == nullptr )
52     {
53       return 0;
54     }
55   }
56   this->NumberOfIds = 0;
57   return 1;
58 }
59 
60 //----------------------------------------------------------------------------
SetNumberOfIds(const vtkIdType number)61 void vtkIdList::SetNumberOfIds(const vtkIdType number)
62 {
63   this->Allocate(number,0);
64   this->NumberOfIds = number;
65 }
66 
67 //----------------------------------------------------------------------------
InsertUniqueId(const vtkIdType vtkid)68 vtkIdType vtkIdList::InsertUniqueId(const vtkIdType vtkid)
69 {
70   for (vtkIdType i=0; i < this->NumberOfIds; i++)
71   {
72     if ( vtkid == this->Ids[i] )
73     {
74       return i;
75     }
76   }
77 
78   return this->InsertNextId(vtkid);
79 }
80 
81 //----------------------------------------------------------------------------
WritePointer(const vtkIdType i,const vtkIdType number)82 vtkIdType *vtkIdList::WritePointer(const vtkIdType i, const vtkIdType number)
83 {
84   vtkIdType newSize=i+number;
85   if ( newSize > this->Size )
86   {
87     this->Resize(newSize);
88   }
89   if ( newSize > this->NumberOfIds )
90   {
91     this->NumberOfIds = newSize;
92   }
93   return this->Ids + i;
94 }
95 
96 //----------------------------------------------------------------------------
SetArray(vtkIdType * array,vtkIdType size)97 void vtkIdList::SetArray(vtkIdType *array, vtkIdType size)
98 {
99   delete [] this->Ids;
100   this->Ids = array;
101   this->NumberOfIds = size;
102   this->Size = size;
103 }
104 
105 //----------------------------------------------------------------------------
DeleteId(vtkIdType vtkid)106 void vtkIdList::DeleteId(vtkIdType vtkid)
107 {
108   vtkIdType i=0;
109 
110   // while loop is necessary to delete all occurrences of vtkid
111   while ( i < this->NumberOfIds )
112   {
113     for ( ; i < this->NumberOfIds; i++)
114     {
115       if ( this->Ids[i] == vtkid )
116       {
117         break;
118       }
119     }
120 
121     // if found; replace current id with last
122     if ( i < this->NumberOfIds )
123     {
124       this->SetId(i,this->Ids[this->NumberOfIds-1]);
125       this->NumberOfIds--;
126     }
127   }
128 }
129 
130 //----------------------------------------------------------------------------
DeepCopy(vtkIdList * ids)131 void vtkIdList::DeepCopy(vtkIdList *ids)
132 {
133   this->SetNumberOfIds(ids->NumberOfIds);
134   if (ids->NumberOfIds > 0)
135   {
136     std::copy(ids->Ids, ids->Ids + ids->NumberOfIds, this->Ids);
137   }
138   this->Squeeze();
139 }
140 
141 //----------------------------------------------------------------------------
Resize(const vtkIdType sz)142 vtkIdType *vtkIdList::Resize(const vtkIdType sz)
143 {
144   vtkIdType *newIds;
145   vtkIdType newSize;
146 
147   if ( sz > this->Size )
148   {
149     newSize = this->Size + sz;
150   }
151   else if (sz == this->Size)
152   {
153     return this->Ids;
154   }
155   else
156   {
157     newSize = sz;
158   }
159 
160   if (newSize <= 0)
161   {
162     this->Initialize();
163     return nullptr;
164   }
165 
166   if ( (newIds = new vtkIdType[newSize]) == nullptr )
167   {
168     vtkErrorMacro(<< "Cannot allocate memory\n");
169     return nullptr;
170   }
171 
172   if (this->NumberOfIds > newSize)
173   {
174     this->NumberOfIds = newSize;
175   }
176 
177   if (this->Ids)
178   {
179     memcpy(newIds, this->Ids,
180            static_cast<size_t>(sz < this->Size ? sz : this->Size) * sizeof(vtkIdType));
181     delete [] this->Ids;
182   }
183 
184   this->Size = newSize;
185   this->Ids = newIds;
186   return this->Ids;
187 }
188 
189 //----------------------------------------------------------------------------
190 #define VTK_TMP_ARRAY_SIZE 500
191 // Intersect this list with another vtkIdList. Updates current list according
192 // to result of intersection operation.
IntersectWith(vtkIdList * otherIds)193 void vtkIdList::IntersectWith(vtkIdList* otherIds)
194 {
195   // Fast method due to Dr. Andreas Mueller of ISE Integrated Systems
196   // Engineering (CH).
197   vtkIdType thisNumIds = this->GetNumberOfIds();
198 
199   if (thisNumIds <= VTK_TMP_ARRAY_SIZE)
200   {//Use fast method if we can fit in temporary storage
201     vtkIdType  thisIds[VTK_TMP_ARRAY_SIZE];
202     vtkIdType i, vtkid;
203 
204     for (i=0; i < thisNumIds; i++)
205     {
206       thisIds[i] = this->GetId(i);
207     }
208     for (this->Reset(), i=0; i < thisNumIds; i++)
209     {
210       vtkid = thisIds[i];
211       if ( otherIds->IsId(vtkid) != (-1) )
212       {
213         this->InsertNextId(vtkid);
214       }
215     }
216   }
217   else
218   {//use slower method for extreme cases
219     vtkIdType *thisIds = new vtkIdType [thisNumIds];
220     vtkIdType  i, vtkid;
221 
222     for (i=0; i < thisNumIds; i++)
223     {
224       *(thisIds + i) = this->GetId(i);
225     }
226     for (this->Reset(), i=0; i < thisNumIds; i++)
227     {
228       vtkid = *(thisIds + i);
229       if ( otherIds->IsId(vtkid) != (-1) )
230       {
231         this->InsertNextId(vtkid);
232       }
233     }
234     delete [] thisIds;
235   }
236 }
237 #undef VTK_TMP_ARRAY_SIZE
238 
239 //----------------------------------------------------------------------------
Sort()240 void vtkIdList::Sort()
241 {
242   if ( this->Ids == nullptr || this->NumberOfIds < 2 )
243   {
244     return;
245   }
246   vtkSMPTools::Sort(this->Ids, this->Ids+this->NumberOfIds);
247 }
248 
249 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)250 void vtkIdList::PrintSelf(ostream& os, vtkIndent indent)
251 {
252   this->Superclass::PrintSelf(os,indent);
253 
254   os << indent << "Number of Ids: " << this->NumberOfIds << "\n";
255 }
256