1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkEdgeTable.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 "vtkEdgeTable.h"
16 #include "vtkIdList.h"
17 #include "vtkObjectFactory.h"
18 #include "vtkPoints.h"
19 #include "vtkVoidArray.h"
20
21 vtkStandardNewMacro(vtkEdgeTable);
22
23 //------------------------------------------------------------------------------
24 // Instantiate object based on maximum point id.
vtkEdgeTable()25 vtkEdgeTable::vtkEdgeTable()
26 {
27 this->Table = nullptr;
28 this->Attributes = nullptr;
29 this->PointerAttributes = nullptr;
30 this->Points = nullptr;
31
32 this->TableMaxId = -1;
33 this->TableSize = 0;
34
35 this->Position[0] = 0;
36 this->Position[1] = -1;
37 this->NumberOfEdges = 0;
38 }
39
40 //------------------------------------------------------------------------------
41 // Free memory and return to instantiated state.
Initialize()42 void vtkEdgeTable::Initialize()
43 {
44 vtkIdType i;
45
46 if (this->Table)
47 {
48 for (i = 0; i < this->TableSize; i++)
49 {
50 if (this->Table[i])
51 {
52 this->Table[i]->Delete();
53 }
54 }
55 delete[] this->Table;
56 this->Table = nullptr;
57 this->TableMaxId = -1;
58
59 if (this->StoreAttributes == 1)
60 {
61 for (i = 0; i < this->TableSize; i++)
62 {
63 if (this->Attributes[i])
64 {
65 this->Attributes[i]->Delete();
66 }
67 }
68 delete[] this->Attributes;
69 this->Attributes = nullptr;
70 }
71 else if (this->StoreAttributes == 2)
72 {
73 for (i = 0; i < this->TableSize; i++)
74 {
75 if (this->PointerAttributes[i])
76 {
77 this->PointerAttributes[i]->Delete();
78 }
79 }
80 delete[] this->PointerAttributes;
81 this->PointerAttributes = nullptr;
82 }
83 } // if table defined
84
85 if (this->Points)
86 {
87 this->Points->Delete();
88 this->Points = nullptr;
89 }
90
91 this->TableSize = 0;
92 this->NumberOfEdges = 0;
93 }
94
95 //------------------------------------------------------------------------------
96 // Free memory and return to instantiated state.
Reset()97 void vtkEdgeTable::Reset()
98 {
99 vtkIdType i;
100
101 if (this->Table)
102 {
103 for (i = 0; i < this->TableSize; i++)
104 {
105 if (this->Table[i])
106 {
107 this->Table[i]->Reset();
108 }
109 }
110
111 if (this->StoreAttributes == 1 && this->Attributes)
112 {
113 for (i = 0; i < this->TableSize; i++)
114 {
115 if (this->Attributes[i])
116 {
117 this->Attributes[i]->Reset();
118 }
119 }
120 }
121 else if (this->StoreAttributes == 2 && this->PointerAttributes)
122 {
123 for (i = 0; i < this->TableSize; i++)
124 {
125 if (this->PointerAttributes[i])
126 {
127 this->PointerAttributes[i]->Reset();
128 }
129 }
130 }
131 } // if table defined
132
133 this->TableMaxId = -1;
134
135 if (this->Points)
136 {
137 this->Points->Reset();
138 }
139
140 this->NumberOfEdges = 0;
141 }
142
143 //------------------------------------------------------------------------------
~vtkEdgeTable()144 vtkEdgeTable::~vtkEdgeTable()
145 {
146 this->Initialize();
147 }
148
149 //------------------------------------------------------------------------------
InitEdgeInsertion(vtkIdType numPoints,int storeAttributes)150 int vtkEdgeTable::InitEdgeInsertion(vtkIdType numPoints, int storeAttributes)
151 {
152 vtkIdType i;
153
154 numPoints = (numPoints < 1 ? 1 : numPoints);
155
156 // Discard old memory if not enough has been previously allocated
157 this->StoreAttributes = storeAttributes;
158 this->TableMaxId = -1;
159
160 if (numPoints > this->TableSize)
161 {
162 this->Initialize();
163 this->Table = new vtkIdList*[numPoints];
164 for (i = 0; i < numPoints; i++)
165 {
166 this->Table[i] = nullptr;
167 }
168
169 if (this->StoreAttributes == 1)
170 {
171 this->Attributes = new vtkIdList*[numPoints];
172 for (i = 0; i < numPoints; i++)
173 {
174 this->Attributes[i] = nullptr;
175 }
176 }
177 else if (this->StoreAttributes == 2)
178 {
179 this->PointerAttributes = new vtkVoidArray*[numPoints];
180 for (i = 0; i < numPoints; i++)
181 {
182 this->PointerAttributes[i] = nullptr;
183 }
184 }
185 this->TableSize = numPoints;
186 }
187
188 // Otherwise, reuse the old memory
189 else
190 {
191 this->Reset();
192 }
193
194 this->Position[0] = 0;
195 this->Position[1] = -1;
196
197 this->NumberOfEdges = 0;
198
199 return 1;
200 }
201
202 //------------------------------------------------------------------------------
203 // Return non-negative if edge (p1,p2) is an edge; otherwise -1.
IsEdge(vtkIdType p1,vtkIdType p2)204 vtkIdType vtkEdgeTable::IsEdge(vtkIdType p1, vtkIdType p2)
205 {
206 vtkIdType index, search;
207
208 if (p1 < p2)
209 {
210 index = p1;
211 search = p2;
212 }
213 else
214 {
215 index = p2;
216 search = p1;
217 }
218
219 if (index > this->TableMaxId || this->Table[index] == nullptr)
220 {
221 return (-1);
222 }
223 else
224 {
225 vtkIdType loc;
226 if ((loc = this->Table[index]->IsId(search)) == (-1))
227 {
228 return (-1);
229 }
230 else
231 {
232 if (this->StoreAttributes == 1)
233 {
234 return this->Attributes[index]->GetId(loc);
235 }
236 else
237 {
238 return 1;
239 }
240 }
241 }
242 }
243
244 //------------------------------------------------------------------------------
245 // Return non-negative if edge (p1,p2) is an edge; otherwise -1.
IsEdge(vtkIdType p1,vtkIdType p2,void * & ptr)246 void vtkEdgeTable::IsEdge(vtkIdType p1, vtkIdType p2, void*& ptr)
247 {
248 vtkIdType index, search;
249
250 if (p1 < p2)
251 {
252 index = p1;
253 search = p2;
254 }
255 else
256 {
257 index = p2;
258 search = p1;
259 }
260
261 if (index > this->TableMaxId || this->Table[index] == nullptr)
262 {
263 ptr = nullptr;
264 }
265 else
266 {
267 vtkIdType loc;
268 if ((loc = this->Table[index]->IsId(search)) == (-1))
269 {
270 ptr = nullptr;
271 }
272 else
273 {
274 if (this->StoreAttributes == 2)
275 {
276 ptr = this->PointerAttributes[index]->GetVoidPointer(loc);
277 }
278 else
279 {
280 ptr = nullptr;
281 }
282 }
283 }
284 }
285
286 //------------------------------------------------------------------------------
287 // Insert the edge (p1,p2) into the table. It is the user's responsibility to
288 // check if the edge has already been inserted.
InsertEdge(vtkIdType p1,vtkIdType p2)289 vtkIdType vtkEdgeTable::InsertEdge(vtkIdType p1, vtkIdType p2)
290 {
291 vtkIdType index, search;
292
293 if (p1 < p2)
294 {
295 index = p1;
296 search = p2;
297 }
298 else
299 {
300 index = p2;
301 search = p1;
302 }
303
304 if (index >= this->TableSize)
305 {
306 this->Resize(index + 1);
307 }
308
309 if (index > this->TableMaxId)
310 {
311 this->TableMaxId = index;
312 }
313
314 if (this->Table[index] == nullptr)
315 {
316 this->Table[index] = vtkIdList::New();
317 this->Table[index]->Allocate(6, 12);
318 if (this->StoreAttributes == 1)
319 {
320 if (this->Attributes[index])
321 {
322 this->Attributes[index]->Delete();
323 }
324 this->Attributes[index] = vtkIdList::New();
325 this->Attributes[index]->Allocate(6, 12);
326 }
327 }
328
329 this->Table[index]->InsertNextId(search);
330 if (this->StoreAttributes == 1)
331 {
332 this->Attributes[index]->InsertNextId(this->NumberOfEdges);
333 }
334 this->NumberOfEdges++;
335
336 return (this->NumberOfEdges - 1);
337 }
338
339 //------------------------------------------------------------------------------
InsertEdge(vtkIdType p1,vtkIdType p2,vtkIdType attributeId)340 void vtkEdgeTable::InsertEdge(vtkIdType p1, vtkIdType p2, vtkIdType attributeId)
341 {
342 vtkIdType index, search;
343
344 if (p1 < p2)
345 {
346 index = p1;
347 search = p2;
348 }
349 else
350 {
351 index = p2;
352 search = p1;
353 }
354
355 if (index >= this->TableSize)
356 {
357 this->Resize(index + 1);
358 }
359
360 if (index > this->TableMaxId)
361 {
362 this->TableMaxId = index;
363 }
364
365 if (this->Table[index] == nullptr)
366 {
367 this->Table[index] = vtkIdList::New();
368 this->Table[index]->Allocate(6, 12);
369 if (this->StoreAttributes == 1)
370 {
371 this->Attributes[index] = vtkIdList::New();
372 this->Attributes[index]->Allocate(6, 12);
373 }
374 }
375
376 this->NumberOfEdges++;
377 this->Table[index]->InsertNextId(search);
378 if (this->StoreAttributes)
379 {
380 this->Attributes[index]->InsertNextId(attributeId);
381 }
382 }
383
384 //------------------------------------------------------------------------------
InsertEdge(vtkIdType p1,vtkIdType p2,void * ptr)385 void vtkEdgeTable::InsertEdge(vtkIdType p1, vtkIdType p2, void* ptr)
386 {
387 vtkIdType index, search;
388
389 if (p1 < p2)
390 {
391 index = p1;
392 search = p2;
393 }
394 else
395 {
396 index = p2;
397 search = p1;
398 }
399
400 if (index >= this->TableSize)
401 {
402 this->Resize(index + 1);
403 }
404
405 if (index > this->TableMaxId)
406 {
407 this->TableMaxId = index;
408 }
409
410 if (this->Table[index] == nullptr)
411 {
412 this->Table[index] = vtkIdList::New();
413 this->Table[index]->Allocate(6, 12);
414 if (this->StoreAttributes == 2)
415 {
416 this->PointerAttributes[index] = vtkVoidArray::New();
417 this->PointerAttributes[index]->Allocate(6, 12);
418 }
419 }
420
421 this->NumberOfEdges++;
422 this->Table[index]->InsertNextId(search);
423 if (this->StoreAttributes == 2)
424 {
425 this->PointerAttributes[index]->InsertNextVoidPointer(ptr);
426 }
427 }
428
429 //------------------------------------------------------------------------------
430 // Initialize traversal of edges in table.
InitTraversal()431 void vtkEdgeTable::InitTraversal()
432 {
433 this->Position[0] = 0;
434 this->Position[1] = -1;
435 }
436
437 // Traverse list of edges in table. Return the edge as (p1,p2), where p1 and
438 // p2 are point id's. Method return value is <0 if the list is exhausted;
439 // otherwise a valid id >=0. The value of p1 is guaranteed to be <= p2. The
440 // return value is an id that can be used for accessing attributes.
GetNextEdge(vtkIdType & p1,vtkIdType & p2)441 vtkIdType vtkEdgeTable::GetNextEdge(vtkIdType& p1, vtkIdType& p2)
442 {
443 for (; this->Position[0] <= this->TableMaxId; this->Position[0]++, this->Position[1] = (-1))
444 {
445 if (this->Table[this->Position[0]] != nullptr &&
446 ++this->Position[1] < this->Table[this->Position[0]]->GetNumberOfIds())
447 {
448 p1 = this->Position[0];
449 p2 = this->Table[this->Position[0]]->GetId(this->Position[1]);
450 if (this->StoreAttributes == 1)
451 {
452 return this->Attributes[this->Position[0]]->GetId(this->Position[1]);
453 }
454 else
455 {
456 return (-1);
457 }
458 }
459 }
460
461 return (-1);
462 }
463
464 //------------------------------------------------------------------------------
465 // Traverse list of edges in table. Return the edge as (p1,p2), where p1 and
466 // p2 are point id's. The value of p1 is guaranteed to be <= p2. The
467 // return value is either 1 for success or 0 if the list is exhausted.
GetNextEdge(vtkIdType & p1,vtkIdType & p2,void * & ptr)468 int vtkEdgeTable::GetNextEdge(vtkIdType& p1, vtkIdType& p2, void*& ptr)
469 {
470 for (; this->Position[0] <= this->TableMaxId; this->Position[0]++, this->Position[1] = (-1))
471 {
472 if (this->Table[this->Position[0]] != nullptr &&
473 ++this->Position[1] < this->Table[this->Position[0]]->GetNumberOfIds())
474 {
475 p1 = this->Position[0];
476 p2 = this->Table[this->Position[0]]->GetId(this->Position[1]);
477 if (this->StoreAttributes == 2)
478 {
479 this->IsEdge(p1, p2, ptr);
480 }
481 else
482 {
483 ptr = nullptr;
484 }
485 return 1;
486 }
487 }
488 return 0;
489 }
490
Resize(vtkIdType size)491 vtkIdList** vtkEdgeTable::Resize(vtkIdType size)
492 {
493 vtkIdList** newTableArray;
494 vtkIdList** newAttributeArray;
495 vtkVoidArray** newPointerAttributeArray;
496 vtkIdType newSize, i;
497 vtkIdType extend = this->TableSize / 2 + 1;
498
499 if (size >= this->TableSize)
500 {
501 newSize = this->TableSize + extend * (((size - this->TableSize) / extend) + 1);
502 }
503 else
504 {
505 newSize = size;
506 }
507
508 size = (size < this->TableSize ? size : this->TableSize);
509 newTableArray = new vtkIdList*[newSize];
510 // NOLINTNEXTLINE(bugprone-sizeof-expression)
511 memcpy(newTableArray, this->Table, size * sizeof(*newTableArray));
512 for (i = size; i < newSize; i++)
513 {
514 newTableArray[i] = nullptr;
515 }
516 this->TableSize = newSize;
517 delete[] this->Table;
518 this->Table = newTableArray;
519
520 if (this->StoreAttributes == 1)
521 {
522 newAttributeArray = new vtkIdList*[newSize];
523 // NOLINTNEXTLINE(bugprone-sizeof-expression)
524 memcpy(newAttributeArray, this->Attributes, size * sizeof(*newAttributeArray));
525 for (i = size; i < newSize; i++)
526 {
527 newAttributeArray[i] = nullptr;
528 }
529 delete[] this->Attributes;
530 this->Attributes = newAttributeArray;
531 }
532 else if (this->StoreAttributes == 2)
533 {
534 newPointerAttributeArray = new vtkVoidArray*[newSize];
535 // NOLINTNEXTLINE(bugprone-sizeof-expression)
536 memcpy(newPointerAttributeArray, this->Attributes, size * sizeof(*newPointerAttributeArray));
537 for (i = size; i < newSize; i++)
538 {
539 newPointerAttributeArray[i] = nullptr;
540 }
541 delete[] this->PointerAttributes;
542 this->PointerAttributes = newPointerAttributeArray;
543 }
544
545 return this->Table;
546 }
547
548 //------------------------------------------------------------------------------
InitPointInsertion(vtkPoints * newPts,vtkIdType estSize)549 int vtkEdgeTable::InitPointInsertion(vtkPoints* newPts, vtkIdType estSize)
550 {
551 // Initialize
552 if (this->Table)
553 {
554 this->Initialize();
555 }
556 if (newPts == nullptr)
557 {
558 vtkErrorMacro(<< "Must define points for point insertion");
559 return 0;
560 }
561 if (this->Points != nullptr)
562 {
563 this->Points->Delete();
564 }
565 // Set up the edge insertion
566 this->InitEdgeInsertion(estSize, 1);
567
568 this->Points = newPts;
569 this->Points->Register(this);
570
571 return 1;
572 }
573
574 //------------------------------------------------------------------------------
InsertUniquePoint(vtkIdType p1,vtkIdType p2,double x[3],vtkIdType & ptId)575 int vtkEdgeTable::InsertUniquePoint(vtkIdType p1, vtkIdType p2, double x[3], vtkIdType& ptId)
576 {
577 vtkIdType loc = this->IsEdge(p1, p2);
578
579 if (loc != -1)
580 {
581 ptId = loc;
582 return 0;
583 }
584 else
585 {
586 ptId = this->InsertEdge(p1, p2);
587 this->Points->InsertPoint(ptId, x);
588 return 1;
589 }
590 }
591
592 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)593 void vtkEdgeTable::PrintSelf(ostream& os, vtkIndent indent)
594 {
595 this->Superclass::PrintSelf(os, indent);
596
597 os << indent << "NumberOfEdges: " << this->GetNumberOfEdges() << "\n";
598 }
599