vtkPolyDataOnionPeelFilter.C 35.8 KB
Newer Older
hrchilds's avatar
hrchilds committed
1 2
/*****************************************************************************
*
bonnell's avatar
bonnell committed
3
* Copyright (c) 2000 - 2016, Lawrence Livermore National Security, LLC
hrchilds's avatar
hrchilds committed
4
* Produced at the Lawrence Livermore National Laboratory
5
* LLNL-CODE-442911
hrchilds's avatar
hrchilds committed
6 7
* All rights reserved.
*
8
* This file is  part of VisIt. For  details, see https://visit.llnl.gov/.  The
hrchilds's avatar
hrchilds committed
9 10 11 12 13 14 15 16 17 18
* full copyright notice is contained in the file COPYRIGHT located at the root
* of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
*
* Redistribution  and  use  in  source  and  binary  forms,  with  or  without
* modification, are permitted provided that the following conditions are met:
*
*  - Redistributions of  source code must  retain the above  copyright notice,
*    this list of conditions and the disclaimer below.
*  - Redistributions in binary form must reproduce the above copyright notice,
*    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
19 20 21
*    documentation and/or other materials provided with the distribution.
*  - Neither the name of  the LLNS/LLNL nor the names of  its contributors may
*    be used to endorse or promote products derived from this software without
hrchilds's avatar
hrchilds committed
22 23 24 25 26
*    specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
27 28 29
* ARE  DISCLAIMED. IN  NO EVENT  SHALL LAWRENCE  LIVERMORE NATIONAL  SECURITY,
* LLC, THE  U.S.  DEPARTMENT OF  ENERGY  OR  CONTRIBUTORS BE  LIABLE  FOR  ANY
* DIRECT,  INDIRECT,   INCIDENTAL,   SPECIAL,   EXEMPLARY,  OR   CONSEQUENTIAL
hrchilds's avatar
hrchilds committed
30 31 32 33 34 35 36 37 38
* DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
* SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
* CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
* LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
* OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*****************************************************************************/

39
// ****************************************************************************
40 41 42 43 44 45 46 47
//  Class:   vtkPolyDataOnionPeelFilter
//
//  Purpose:
//    Derived type of vtkPolyDataToPolyDataFilter.
//
//  Programmer:  Kathleen S. Bonnell
//  Creation:  5 October 2000
//
48
// ****************************************************************************
49 50 51 52

#include <vtkCell.h>
#include <vtkCellData.h>
#include <vtkIdList.h>
53 54
#include <vtkInformation.h>
#include <vtkInformationVector.h>
55 56 57 58 59 60 61 62 63 64
#include <vtkIntArray.h>
#include <vtkObjectFactory.h>
#include <vtkPolyDataOnionPeelFilter.h>
#include <vtkPointData.h>
#include <vtkRectilinearGrid.h>
#include <vtkStructuredGrid.h>
#include <vtkPolyData.h>
#include <vtkUnsignedIntArray.h>
#include <vtkVisItUtility.h>

65 66 67 68
// ****************************************************************************
//  Modifications:
//    Kathleen Bonnell, Wed Mar  6 15:14:29 PST 2002 
//    Replace 'New' method with Macro to match VTK 4.0 API. 
69
//
70 71
// ****************************************************************************

72 73 74
vtkStandardNewMacro(vtkPolyDataOnionPeelFilter);


75 76
// ****************************************************************************
//  Constructor: vtkPolyDataOnionPeelFilter
77
//
78 79 80 81 82 83 84
//  Purpose:
//    Construct with adjacency set to Node-Adjacency.
//    SeedCellId set to 0, RequestedLayer set to 0
//
//  Modifications:
//    Kathleen Bonnell, Thu Aug 15 18:37:59 PDT 2002 
//    Initialize logicalIndex and useLogicalIndex. 
85
//
86 87
//    Kathleen Bonnell, Tue Jan 18 19:37:46 PST 2005 
//    Initialize ReconstructOriginalCells. 
88
//
89 90
//    Kathleen Bonnell, Wed Jan 19 15:54:38 PST 2005 
//    Renamed 'SeedCellId' to 'SeedId'.  Initialize SeedIdIsForCell. 
91
//
92 93
// ****************************************************************************

94 95 96 97 98 99 100
vtkPolyDataOnionPeelFilter::vtkPolyDataOnionPeelFilter()
{
    this->RequestedLayer = 0;
    this->SeedId = 0;
    this->logicalIndex[0] = this->logicalIndex[1] = this->logicalIndex[2] = 0;
    this->useLogicalIndex = false;
    this->maxLayersReached = 0;
bonnell's avatar
bonnell committed
101
    this->maxLayerNum = VTK_INT_MAX;
102
    this->AdjacencyType = VTK_NODE_ADJACENCY;
bonnell's avatar
bonnell committed
103 104
    this->ReconstructOriginalCells = false; 
    this->SeedIdIsForCell = true; 
105 106 107 108 109 110 111 112 113 114 115

    this->layerCellIds = vtkIdList::New();
    this->layerCellIds->Allocate(500);
    this->cellOffsets = vtkIdList::New();
    this->cellOffsets->Allocate(50);

    this->bsc_callback = NULL;
    this->bsc_args = NULL;
}


116 117 118 119
// ****************************************************************************
//  Destructor: ~vtkPolyDataOnionPeelFilter
//
// ****************************************************************************
120 121 122 123 124 125 126 127 128 129

vtkPolyDataOnionPeelFilter::~vtkPolyDataOnionPeelFilter()
{
    this->layerCellIds->Delete();
    this->layerCellIds = NULL;

    this->cellOffsets->Delete();
    this->cellOffsets = NULL;
}

130 131 132

// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::SetBadSeedCallback
133
//
134 135
//  Purpose:
//    Sets a callback that is called if the seed cell is bad.
136
// 
137 138 139
//  Arguments:
//    cb      The callback.
//    args    The arguments to cb.
140
// 
141
//  Returns:  None 
142
// 
143 144
//  Programmer: Hank Childs
//  Creation:   May 22, 2002
145
//
146 147 148 149 150 151
//  Modifications:
//    Kathleen Bonnell, Wed Jan 19 15:54:38 PST 2005
//    Removed 'Cell' from method name, arg name.
//
// ****************************************************************************

152 153 154 155 156 157 158
void 
vtkPolyDataOnionPeelFilter::SetBadSeedCallback(BadSeedCallback cb, void *args)
{
    bsc_callback = cb;
    bsc_args     = args;
}

159 160 161

// ****************************************************************************
//  Method:   vtkPolyDataOnionPeelFilter::Initialize
162
//
163 164
//  Purpose:  
//    Initialize data members in preparation for new layers.
165
// 
166
//  Arguments:  None
167
// 
168
//  Returns:  None 
169
// 
170 171 172 173
//  Assumptions and Comments:
//    Intialization should occur when certain fields of the filter have been
//    modified.  Namely input to the filter, SeedCellId, and
//    AdjacencyType.  Modification of RequestedLayer requires no initialization.
174
//
175 176 177
//    first item (slot 0) of layerCellIds is always SeedCellId
//    first item (slot 0) of cellOffsets is always adjacenyType 
//    (used for modification check in Execute method).
178
//
179 180
//  Programmer: Kathleen S. Bonnell
//  Creation:   5 October 2000
181
//
182 183 184
//  Modifications:
//    Hank Childs, Wed May 22 16:59:53 PDT 2002
//    Also call a callback if the seed cell is invalid.
185
//
186 187 188
//    Kathleen Bonnell, Thu Aug 15 17:48:38 PDT 2002  
//    Since we are issuing an error callback for a bad seed,
//    don't allow further processing. 
189
//
190 191
//    Hank Childs, Fri Aug 27 15:15:20 PDT 2004
//    Renamed ghost data arrays.
192
//
193 194 195 196 197 198 199
//    Kathleen Bonnell, Tue Jan 18 19:37:46 PST 2005 
//    Addeed logic to handle requests for reconstructing original cells,
//    e.g. when connectivity of original input has changed.
//
//    Kathleen Bonnell, Wed Jan 19 15:54:38 PST 2005 
//    Renamed 'SeedCellId to 'SeedId', 'numCells' arg to 'numIds'.
//    Added code to handle seedId that is a node. 
200
// 
201 202 203 204
//    Eric Brugger, Wed Jan  9 12:05:05 PST 2013
//    Modified to inherit from vtkPolyDataAlgorithm.
//
// ****************************************************************************
205 206

bool 
207
vtkPolyDataOnionPeelFilter::Initialize()
208 209
{
    this->maxLayersReached = 0;
bonnell's avatar
bonnell committed
210
    this->maxLayerNum = VTK_INT_MAX;
211

212 213 214 215 216
    int numIds;
    if (this->SeedIdIsForCell)
       numIds = input->GetNumberOfCells();
    else 
       numIds = input->GetNumberOfPoints();
217 218 219 220 221 222

    if (useLogicalIndex)
    {
        int dims[3] = { 1, 1, 1};
        if (input->GetDataObjectType() == VTK_STRUCTURED_GRID)
        {
223
            ((vtkStructuredGrid*)input)->GetDimensions(dims);
224 225 226
        }
        else if (input->GetDataObjectType() == VTK_RECTILINEAR_GRID)
        {
227
            ((vtkRectilinearGrid*)input)->GetDimensions(dims);
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
        }
        if (this->logicalIndex[0] >= dims[0] ||
            this->logicalIndex[1] >= dims[1] ||
            this->logicalIndex[2] >= dims[2])
        {
            if (bsc_callback != NULL) 
            {
                bsc_callback(bsc_args, SeedId, numIds, false);
           
            } 
            vtkWarningMacro(<<"SeedIndex (" << this->logicalIndex[0] << " "
                << this->logicalIndex[1] << " " << this->logicalIndex[2] 
                << ")  Exceeds dimensions of dataset ("
                << dims[0] << " " << dims[1] << " " << dims[2] << ").");
            return false; //unsuccessful initialization
        } 
        if (this->SeedIdIsForCell)
        {
            this->SeedId = this->logicalIndex[2]*(dims[0]-1)*(dims[1]-1) + 
                           this->logicalIndex[1]*(dims[0]-1) + 
                           this->logicalIndex[0];
        } 
        else 
        {
            this->SeedId = this->logicalIndex[2]*(dims[0])*(dims[1]) + 
                           this->logicalIndex[1]*(dims[0]) + 
                           this->logicalIndex[0];
        } 
    }
    // check for out-of-range error on seedcellId;
    if (!this->ReconstructOriginalCells &&
       (this->SeedId < 0 || this->SeedId >= numIds) )
    {
        if (bsc_callback != NULL) 
        {
            if (useLogicalIndex)
            {
                bsc_callback(bsc_args, SeedId, numIds, false);
            }
            else 
            {
                bsc_callback(bsc_args, SeedId, numIds, false);
            }
        }
        vtkWarningMacro(<<"SeedId " << this->SeedId << " is Invalid."
                        <<"\nValid ids range from 0 to " << numIds-1 << ".");
        return false; //unsuccessful initialization
    }
    //
    // check if seedcellId is a ghost cell;
    //
    vtkDataArray *ghosts;
    if (this->SeedIdIsForCell)
       ghosts = input->GetCellData()->GetArray("avtGhostZones");
    else
       ghosts = input->GetCellData()->GetArray("avtGhostNodes");
    if (ghosts)
    {
        if (ghosts->GetComponent(this->SeedId, 0) != 0)
        {
            if (bsc_callback != NULL) 
            {
                if (useLogicalIndex)
                {
                    bsc_callback(bsc_args, SeedId, numIds, true);
                }
                else 
                {
                    bsc_callback(bsc_args, SeedId, numIds, true);
                }
            }
            vtkWarningMacro(<<"SeedId " << this->SeedId << " is a Ghost Cell.");
            return false; //unsuccessful initialization
        }
    }

    this->layerCellIds->Reset();
    this->cellOffsets->Reset();
    if (this->SeedIdIsForCell)
    {
        if (!this->ReconstructOriginalCells)
        {
            this->layerCellIds->InsertNextId(this->SeedId);
        }
        else 
        {
            this->FindCellsCorrespondingToOriginal(this->SeedId, this->layerCellIds);
            if (this->layerCellIds->GetNumberOfIds() == 0) 
            {
                if (bsc_callback != NULL) 
                    bsc_callback(bsc_args, SeedId, numIds, false);
                vtkWarningMacro(<<"SeedId " << this->SeedId 
                                << " is not available from current data.");
                return false; //unsuccessful initialization
            }
        }
    }
    else  //SeedId is a node Id
    {
        if (!this->ReconstructOriginalCells)
        {
329
            input->GetPointCells(this->SeedId, this->layerCellIds); 
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
            if (this->layerCellIds->GetNumberOfIds() == 0) 
            {
                if (bsc_callback != NULL) 
                    bsc_callback(bsc_args, SeedId, numIds, false);
                vtkWarningMacro(<<"SeedId " << this->SeedId 
                                << " is not available from current data.");
                return false; //unsuccessful initialization
            }
        }
        else 
        {
            int i;
            vtkIdList *nodes = vtkIdList::New();
            this->FindNodesCorrespondingToOriginal(this->SeedId, nodes);
            if (nodes->GetNumberOfIds() == 0)
            {
                if (bsc_callback != NULL) 
                    bsc_callback(bsc_args, SeedId, numIds, false);
                vtkWarningMacro(<<"SeedId " << this->SeedId 
                                << " is not available from current data.");
                return false; //unsuccessful initialization
            }
            vtkIdList *neighbors = vtkIdList::New();
            for (i = 0; i < nodes->GetNumberOfIds(); i++)
            {
                input->GetPointCells(nodes->GetId(i), neighbors);        
                for (int nId = 0; nId < neighbors->GetNumberOfIds(); nId++)
                {
                    this->layerCellIds->InsertUniqueId(neighbors->GetId(nId));
                }
            }
            nodes->Delete();
            neighbors->Delete();
            vtkUnsignedIntArray *origCells = vtkUnsignedIntArray::SafeDownCast(
364
                input->GetCellData()->GetArray("avtOriginalCellNumbers"));
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397

            if (origCells)
            {
                unsigned int *oc = origCells->GetPointer(0);
                int nc = origCells->GetNumberOfComponents();
                int comp = nc -1;
                vtkIdList *origIds = vtkIdList::New();
                for (i = 0; i < this->layerCellIds->GetNumberOfIds(); i++)
                {
                        int cellId = this->layerCellIds->GetId(i);
                        int index = cellId *nc + comp;;
                        origIds->InsertNextId(oc[index]);
                }
                FindCellsCorrespondingToOriginal(origIds, this->layerCellIds);
                origIds->Delete();
            }
            
            if (this->layerCellIds->GetNumberOfIds() == 0) 
            {
                if (bsc_callback != NULL) 
                    bsc_callback(bsc_args, SeedId, numIds, false);
                vtkWarningMacro(<<"SeedId " << this->SeedId 
                                << " is not available from current data.");
                return false; //unsuccessful initialization
            }
        }
    }
    //layer 0 offset always zero, so use zeroth slot to indicate AdjacencyType
    this->cellOffsets->InsertNextId(this->AdjacencyType);
    return true; // successful initialization
} // Initialize


398 399
// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::Grow
400
//
401 402 403
//  Purpose:
//    Adds more layers to the onion peel, up to the layer requested by
//    the user or grid boundaries, whichever is reached first.
404
//
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
//  Arguments:  None
//
//  Returns:    None 
//
//  Assumptions and Comments:
//    This method will stop attempting to grow layers when grid
//    boundaries are reached and no more neighbors can be found.  At
//    which point, a warning message is issued and RequestedLayer is
//    set to the maximum layers possible for the current conditions.
//
//  Programmer: Kathleen S. Bonnell
//  Creation:   5 October 2000
//
//  Modifications:
//    Kathleen Bonnell, Thu Aug 15 17:48:38 PDT 2002  
//    Coding style update.
421
//  
422 423 424 425 426 427
//    Kathleen Bonnell, Tue Jan 18 19:37:46 PST 2005 
//    Addeed logic to handle requests for reconstructing original cells,
//    e.g. when connectivity of original input has changed.
//
//    Eric Brugger, Wed Jan  9 12:05:05 PST 2013
//    Modified to inherit from vtkPolyDataAlgorithm.
428
//
429 430
// ****************************************************************************

431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
void 
vtkPolyDataOnionPeelFilter::Grow()
{
    vtkIdList  *currentLayerList  = vtkIdList::New();
    int         totalCurrentCells = this->layerCellIds->GetNumberOfIds();
    int         totalLayersGrown  = this->cellOffsets->GetNumberOfIds() - 1;
    int         start = 0, i = 0, j = 0;

    vtkDebugMacro(<<"Grow::");
    while (this->cellOffsets->GetNumberOfIds() <= this->RequestedLayer ) 
    {
        if (this->maxLayersReached) 
        {
            // cannot create more layers, no more neighbors, we
            //  must be at the boundaries of the grid so stop this loop
            vtkWarningMacro(<<"Grid Boundaries reached. \nRequestedLayer has "
                            <<"been set to the maxLayerNum possible.");

            this->RequestedLayer  = this->maxLayerNum 
                                  = this->cellOffsets->GetNumberOfIds()-1;
            break;
        }

        // create list of cell ids for last layer that was grown

        if (totalLayersGrown == 0) 
            start  = 0;
        else
            start = this->cellOffsets->GetId(totalLayersGrown);

        currentLayerList->SetNumberOfIds(this->layerCellIds->GetNumberOfIds() 
                                        - start);

        for (i = start,j = 0; i < this->layerCellIds->GetNumberOfIds(); i++, j++) 
        {
            currentLayerList->InsertId(j, this->layerCellIds->GetId(i));
        }

        // now add another layer by finding neighbors of cells in previous layer 

        if (this->AdjacencyType == VTK_FACE_ADJACENCY)  
        {
            FindCellNeighborsByFaceAdjacency(currentLayerList, this->layerCellIds);
        }
        else
        {
            FindCellNeighborsByNodeAdjacency(currentLayerList, this->layerCellIds);
        }

        // did we add new cells??? 
        if (this->layerCellIds->GetNumberOfIds() > totalCurrentCells) 
        {
            if (this->ReconstructOriginalCells)
            {
                vtkUnsignedIntArray *origCells = vtkUnsignedIntArray::SafeDownCast(
486
                  input->GetCellData()->GetArray("avtOriginalCellNumbers"));
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523

                if (origCells)
                {
                    unsigned int *oc = origCells->GetPointer(0);
                    int nc = origCells->GetNumberOfComponents();
                    int comp = nc -1;
                    vtkIdList *origIds = vtkIdList::New();
                    start = totalCurrentCells;
                    for (i = start; i < this->layerCellIds->GetNumberOfIds(); i++)
                    {
                        int cellId = this->layerCellIds->GetId(i);
                        int index = cellId *nc + comp;;
                        origIds->InsertNextId(oc[index]);
                    }
                    FindCellsCorrespondingToOriginal(origIds, this->layerCellIds);
                    origIds->Delete();
                }
            }
            // set the offset for this new layer of cells
            this->cellOffsets->InsertNextId(totalCurrentCells);
            totalCurrentCells = this->layerCellIds->GetNumberOfIds();
        }
        else 
        {
            vtkDebugMacro("Grow:  No neighbors found");
            this->maxLayersReached = 1;
        }

        currentLayerList->Reset();
   
    } /* end while */

    currentLayerList->Delete();

} // Grow()


524 525
// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::RequestData
526
//
527 528 529 530
//  Purpose:  
//    vtk Required method. Updates state of the filter by growing
//    onion peel layers as necessary and generating output grid. 
//    Performs error checking on data set type.
531
//
532
//  Arguments:  None
533
//
534
//  Returns:    None 
535
//
536 537 538 539
//  Assumptions and Comments:
//    Assumes this filter's input data set is rectilinear, structured
//    or unstructured grid only.  Check for this condition performed
//    in RequestData() method.
540
//
541 542
//    Passes along all of the input points and point data, but on.y
//    cells and cell data corresponding to requested layers.
543
//
544 545 546 547 548 549 550 551 552 553 554 555 556 557
//  Programmer: Kathleen S. Bonnell
//  Creation:   5 October 2000
//
//  Modifications:
//    Kathleen Bonnell, Tue Sep 25 14:32:46 PDT 2001
//    Removed tests for modification, re-excute from scratch each time
//    as is appropriate for the VisIt pipeline.
//
//    Kathleen Bonnell, Thu Aug 15 17:48:38 PDT 2002  
//    Made Initialize return a bool indicating wheter the initialization
//    was a success or not.  If not, don't process further. 
//
//    Kathleen Bonnell, Wed Jan 19 15:54:38 PST 2005 
//    Use different args for Initialize when seedId is for a node. 
558
//
559 560 561 562
//    Eric Brugger, Wed Jan  9 12:05:05 PST 2013
//    Modified to inherit from vtkPolyDataAlgorithm.
//
// ****************************************************************************
563

564 565 566 567 568
int
vtkPolyDataOnionPeelFilter::RequestData(
    vtkInformation *vtkNotUsed(request),
    vtkInformationVector **inputVector,
    vtkInformationVector *outputVector)
569
{
570 571 572
    // get the info objects
    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
    vtkInformation *outInfo = outputVector->GetInformationObject(0);
573

574 575 576 577 578 579 580
    //
    // Initialize some frequently used values.
    //
    input  = vtkDataSet::SafeDownCast(
        inInfo->Get(vtkDataObject::DATA_OBJECT()));
    output = vtkPolyData::SafeDownCast(
        outInfo->Get(vtkDataObject::DATA_OBJECT()));
581 582 583 584 585

    vtkDebugMacro(<<"Generating PolyDataOnionPeelFilter Layers");

    bool success;
    if (this->SeedIdIsForCell)
586
       success = this->Initialize();
587
    else 
588
       success = this->Initialize();
589 590 591

    if (!success)
    {
592
        return 1;
593 594
    }

595
    // check for out-of-range error on RequestedLayer
596 597 598 599 600 601 602 603 604 605 606 607 608
    if (RequestedLayer > this->maxLayerNum) 
    {
        vtkWarningMacro(<<"Requested Layer greater than max layers possible."
        <<"\nRequestedLayer has been set to the max possible:  "
        << this->maxLayerNum << ".");

        this->RequestedLayer  = this->maxLayerNum ;
    }

    Grow();

    this->GenerateOutputGrid();

609 610
    return 1;
} // RequestData
611 612

      
613 614
// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::FillInputPortInformation
615
//
616 617
//  Purpose:  
//    Specifies that the input must be a vtkDataSet. 
618
//
619 620
//  Arguments:
//    info    The input port information
621
//
622 623
//  Returns:
//    1
624
//
625 626 627 628
//  Assumptions and Comments:
//
//  Programmer: Eric Brugger
//  Creation:   Wed Jan  9 12:05:05 PST 2013
629
//
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
// ****************************************************************************

int
vtkPolyDataOnionPeelFilter::FillInputPortInformation(int, vtkInformation *info)
{
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");

    return 1;
} // FillInputPortInformation


// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::GenerateOutputGrid
//
//  Purpose:  
//    Creates the unstructured grid for output. 
//
//  Arguments:  None
//
//  Returns:    None 
//
//  Assumptions and Comments:
//    Assumes this filter's input data set is rectilinear, structured
//    or unstructured grid only.  Check for this condition performed
//    in Execute() method.
//
//    Passes along all of the input points and point data, but on.y
//    cells and cell data corresponding to requested layers.
//
//  Programmer: Kathleen S. Bonnell
//  Creation:   5 October 2000
//
//  Modifications:
//    Kathleen Bonnell, Thu Aug 15 17:48:38 PDT 2002  
//    Coding style update.
//
//    Kathleen Bonnell, Tue Jun 24 14:19:49 PDT 2003 
//    Allow for poly-data input, retrieve points via
//    vtkVisItUtility::GetPoints. 
//
//    Hank Childs, Thu Mar 10 09:48:47 PST 2005
//    Fix memory leak.
//
//    Eric Brugger, Wed Jan  9 12:05:05 PST 2013
//    Modified to inherit from vtkPolyDataAlgorithm.
//
// ****************************************************************************

678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
void 
vtkPolyDataOnionPeelFilter::GenerateOutputGrid()
{
    vtkDebugMacro(<<"GenerateOutputGrid::");

    vtkPointData        *inPD       = input->GetPointData();
    vtkCellData         *inCD       = input->GetCellData();
    vtkPointData        *outPD      = output->GetPointData();
    vtkCellData         *outCD      = output->GetCellData();
    vtkIdList           *cellPts    = vtkIdList::New();
    int i, cellId, newCellId, totalCells;

    if (this->RequestedLayer < this->cellOffsets->GetNumberOfIds() -1)
    {
        totalCells = this->cellOffsets->GetId(this->RequestedLayer + 1);
    }
    else
    {
        totalCells =  this->layerCellIds->GetNumberOfIds();
    }
    output->Allocate(totalCells);

    // grab points from input so they can be passed along directly to ouput
    vtkPoints *pts = vtkVisItUtility::GetPoints(input);
    output->SetPoints(pts);
    pts->Delete();
 
    outPD->PassData(inPD);
    outCD->CopyAllocate(inCD);

    // grab only the cell data that corresponds to cells in our layers
    for (i = 0; i < totalCells; i++) 
    {
        cellId = layerCellIds->GetId(i);
        input->GetCellPoints(cellId, cellPts);
        newCellId = output->InsertNextCell(input->GetCellType(cellId), cellPts);
        outCD->CopyData(inCD, cellId, newCellId);
    }

    // free up unused memory in output
    output->Squeeze();

    // free memory used locally
    cellPts->Delete();

} // GenerateOutputGrid


726 727
// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::PrintSelf
728
//
729
//  Purpose:  Prints pertinent information regarding the state of this class 
730 731
//           to the given output stream.
//
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
//  Arguments:
//    os      The output stream to which the information is printed
//    indent  The amount of spaces to indent.
//
//  Returns:  None 
//
//  Assumptions and Comments:
//    Calls the superclass method first. 
//
//  Programmer: Kathleen S. Bonnell
//  Creation:   5 October 2000
//
//  Modifications:
//    Kathleen Bonnell, Thu Aug 15 17:48:38 PDT 2002  
//    Coding style update.
//
// ****************************************************************************

750 751 752 753 754 755 756 757 758 759 760 761
void 
vtkPolyDataOnionPeelFilter::PrintSelf(ostream& os, vtkIndent indent)
{
    this->Superclass::PrintSelf(os,indent);

    os << indent << "Seed Cell Id:    " << this->SeedId << "\n";
    os << indent << "Requested Layer: " << this->RequestedLayer << "\n";
    os << indent << "Adjacency Type:  " 
       << this->GetAdjacencyTypeAsString() << "\n";
}


762 763
// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::FindCellNeighborsByNodeAdjacency
764
//
765
//  Purpose: Finds all cells in the input grid that share a node with
766 767
//           the given cell. 
//
768 769 770 771
//  Arguments:
//    prevLayerIds       The unique id numbers of the cells for which 
//                       we want to find neighbors 
//    neighborCellIds    Pointer to list of cells in the onion peel layers 
772
//
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
//  Returns:             None 
//
//  Assumptions and Comments:
//    upon entry to the method, neighborCellIds contains cell ids from 
//    previously grown layers.  This method adds new (unique) neighbor 
//    cell ids to the list.
//
//    It is assumed that cellId represents a valid cell
//
//  Programmer: Kathleen S. Bonnell
//  Creation:   5 October 2000
//
//  Modifications:
//    Kathleen Bonnell, Thu Aug 15 17:48:38 PDT 2002  
//    Coding style update.
//
//    Eric Brugger, Wed Jan  9 12:05:05 PST 2013
//    Modified to inherit from vtkPolyDataAlgorithm.
//
// ****************************************************************************

794
void 
795 796
vtkPolyDataOnionPeelFilter::FindCellNeighborsByNodeAdjacency(
    vtkIdList *prevLayerIds, vtkIdList* neighborCellIds)
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823
{
    vtkIdList  *ids        = vtkIdList::New();
    vtkIdList  *neighbors  = vtkIdList::New();
    int         pntId;
    int         nId;
    int         i;

    for (i = 0; i < prevLayerIds->GetNumberOfIds(); i++) 
    {
        input->GetCellPoints(prevLayerIds->GetId(i), ids);

        for (pntId = 0; pntId < ids->GetNumberOfIds(); pntId++) 
        {
            input->GetPointCells(ids->GetId(pntId), neighbors);        

            for (nId = 0; nId < neighbors->GetNumberOfIds(); nId++)
            {
                neighborCellIds->InsertUniqueId(neighbors->GetId(nId));
            }
        }
    }

    neighbors->Delete();
    ids->Delete();
}


824 825
// ****************************************************************************
//  Method:   vtkPolyDataOnionPeelFilter::FindCellNeighborsByFaceAdjacency
826
//
827 828
//  Purpose:  Finds all cells in the input grid that share a face with
//            the given cell.
829
//
830 831 832 833
//  Arguments:
//    cellId             The unique id number of the cell for which 
//                       we want to find neighbors 
//    neighborCellIds    Pointer to list of cells in the onion peel layers 
834
//
835
//  Returns:             None 
836
//
837 838 839 840
//  Assumptions and Comments:
//    upon entry to the method, neighborCellIds contains cell ids from 
//    previously grown layers.  This method adds new (unique) neighbor 
//    cell ids to the list.
841
//
842
//    It is assumed that cellId represents a valid cell
843
//
844 845
//    This method does not consider cells below 3D when determining
//    face neighbors.
846
//
847 848 849 850 851 852 853 854 855 856 857 858 859 860
//  Programmer: Kathleen S. Bonnell
//  Creation:   5 October 2000
//
//  Modifications:
//    Kathleen S. Bonnell, Mon Oct 30 10:37:56 PST 2000
//    Added neighbor search via edges for 2D cells. 
//
//    Kathleen Bonnell, Thu Aug 15 17:48:38 PDT 2002  
//    Coding style update.
//
//    Eric Brugger, Wed Jan  9 12:05:05 PST 2013
//    Modified to inherit from vtkPolyDataAlgorithm.
//
// ****************************************************************************
861 862

void 
863 864
vtkPolyDataOnionPeelFilter::FindCellNeighborsByFaceAdjacency(
    vtkIdList* prevLayerIds, vtkIdList* neighborCellIds)
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914
{
    vtkIdList  *neighbors = vtkIdList::New();
    vtkIdList  *facePts   = NULL;
    vtkIdList  *edgePts   = NULL;
    vtkCell    *cell      = NULL;
    int         faceId;
    int         edgeId;
    int         nId;
    int         i;
    int         cellId;
  
    for (i = 0; i < prevLayerIds->GetNumberOfIds(); i++) 
    {
        cellId = prevLayerIds->GetId(i);
        cell = input->GetCell(cellId);

        if (cell->GetCellDimension() > 2) 
        {
            for (faceId = 0; faceId < cell->GetNumberOfFaces(); faceId++) 
            {
                facePts = (cell->GetFace(faceId))->GetPointIds();

                input->GetCellNeighbors(cellId, facePts, neighbors);

                for (nId = 0; nId < neighbors->GetNumberOfIds(); nId++) 
                {
                    neighborCellIds->InsertUniqueId(neighbors->GetId(nId));
                }
            }
        } 
        else 
        {
            for (edgeId = 0; edgeId < cell->GetNumberOfEdges(); edgeId++) 
            {
                edgePts = (cell->GetEdge(edgeId))->GetPointIds();

                input->GetCellNeighbors(cellId, edgePts, neighbors);

                for (nId = 0; nId < neighbors->GetNumberOfIds(); nId++) 
                {
                    neighborCellIds->InsertUniqueId(neighbors->GetId(nId));
                }
            }
        }
    }
  
    neighbors->Delete();
}


915 916
// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::SetLogicalIndex
917
//
918 919
//  Purpose:  
//    Set the logical index. 
920
//
921 922
//  Arguments:  
//    i, j, k   The components of the logical Index.
923
//
924
//  Returns:    None 
925
//
926 927 928 929 930 931
//  Programmer: Kathleen Bonnell
//  Creation:   August 15, 2002 
//
//  Modifications:
//
// ****************************************************************************
932 933

void
934 935
vtkPolyDataOnionPeelFilter::SetLogicalIndex(const int i, const int j,
    const int k)
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950
{  
    if (!useLogicalIndex ||
        (this->logicalIndex[0] != i) || 
        (this->logicalIndex[1] != j) || 
        (this->logicalIndex[2] != k) )
    {
        this->logicalIndex[0] = i;
        this->logicalIndex[1] = j;
        this->logicalIndex[2] = k;
        this->Modified();
    }
    useLogicalIndex = true;
}


951 952
// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::SetSeedId
953
//
954 955
//  Purpose:  
//    Set the seed cell id. 
956
//
957 958
//  Arguments:  
//    seed   The new seed cell id.
959
//
960
//  Returns:    None 
961
//
962 963 964 965 966 967
//  Programmer: Kathleen Bonnell
//  Creation:   August 15, 2002 
//
//  Modifications:
//
// ****************************************************************************
968 969 970 971 972 973 974 975 976 977 978 979 980

void
vtkPolyDataOnionPeelFilter::SetSeedId(const int seed)
{  
    if (useLogicalIndex || this->SeedId != seed)
    {
        this->SeedId = seed;
        this->Modified();
    }
    useLogicalIndex = false;
}


981 982
// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::FindCellsCorrespondingToOriginal
983
//
984 985 986
//  Purpose:  
//    Finds all cells whose 'originalCell' designation matches the
//    original id passed as arg. 
987
//
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
//  Arguments:  
//    orig      The original cell id. 
//    group     A place to store the corresponding cells.
//
//  Returns:    None 
//
//  Programmer: Kathleen Bonnell
//  Creation:   January 18, 2005 
//
//  Modifications:
//    Kathleen Bonnell, Tue Jun 14 11:45:21 PDT 2005
//    Correct 'n' for loop counting.
//
//    Eric Brugger, Wed Jan  9 12:05:05 PST 2013
//    Modified to inherit from vtkPolyDataAlgorithm.
//
// ****************************************************************************
1005 1006

void
1007 1008
vtkPolyDataOnionPeelFilter::FindCellsCorrespondingToOriginal(
    int orig, vtkIdList *group)
1009 1010
{
    vtkUnsignedIntArray *origCells = vtkUnsignedIntArray::SafeDownCast(
1011
        input->GetCellData()->GetArray("avtOriginalCellNumbers"));
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021

    if (origCells)
    {
        unsigned int *oc = origCells->GetPointer(0);
        int nc = origCells->GetNumberOfComponents();
        int n = origCells->GetNumberOfTuples() *nc;
        int comp = nc -1;
        for (int i = comp; i < n; i+=nc )
        {
            int id = i / nc;
1022
            if (oc[i] == (unsigned int)orig && group->IsId(id) == -1)
1023 1024 1025 1026 1027 1028
                group->InsertNextId(id);
        }
    }
}


1029 1030
// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::FindCellsCorrespondingToOriginal
1031
//
1032 1033 1034
//  Purpose:  
//    Finds all cells whose 'originalCell' designation matches the
//    original ids passed as arg. 
1035
//
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
//  Arguments:  
//    origs     A list of original ids. 
//    group     A place to store the corresponding cells.
//
//  Returns:    None 
//
//  Programmer: Kathleen Bonnell
//  Creation:   January 18, 2005 
//
//  Modifications:
//    Kathleen Bonnell, Tue Jun 14 11:45:21 PDT 2005
//    Correct 'n' for loop counting.
//
//    Eric Brugger, Wed Jan  9 12:05:05 PST 2013
//    Modified to inherit from vtkPolyDataAlgorithm.
//
// ****************************************************************************
1053 1054

void
1055 1056
vtkPolyDataOnionPeelFilter::FindCellsCorrespondingToOriginal(
    vtkIdList *origs, vtkIdList *group)
1057 1058
{
    vtkUnsignedIntArray *origCells = vtkUnsignedIntArray::SafeDownCast(
1059
        input->GetCellData()->GetArray("avtOriginalCellNumbers"));
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075

    if (origCells)
    {
        unsigned int *oc = origCells->GetPointer(0);
        int nc = origCells->GetNumberOfComponents();
        int n = origCells->GetNumberOfTuples()*nc;
        int comp = nc -1;
        for (int i = comp; i < n; i+=nc)
        {
            int id = i / nc;
            if (origs->IsId(oc[i]) != -1 && group->IsId(id) == -1)
                group->InsertNextId(id);
        }
    }
}

1076 1077 1078

// ****************************************************************************
//  Method: vtkPolyDataOnionPeelFilter::FindNodesCorrespondingToOriginal
1079
//
1080 1081 1082
//  Purpose:  
//    Finds all nodes whose 'originalNode' designation matches the
//    original id passed as arg. 
1083
//
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
//  Arguments:  
//    orig      The original node id. 
//    group     A place to store the corresponding cells.
//
//  Returns:    None 
//
//  Programmer: Kathleen Bonnell
//  Creation:   January 19, 2005 
//
//  Modifications:
//    Kathleen Bonnell, Tue Jun 14 11:45:21 PDT 2005
//    Correct 'n' for loop counting.
//
//    Eric Brugger, Wed Jan  9 12:05:05 PST 2013
//    Modified to inherit from vtkPolyDataAlgorithm.
//
// ****************************************************************************
1101 1102

void
1103 1104
vtkPolyDataOnionPeelFilter::FindNodesCorrespondingToOriginal(
    int orig, vtkIdList *group)
1105 1106
{
    vtkIntArray *origNodes = vtkIntArray::SafeDownCast(
1107
        input->GetPointData()->GetArray("avtOriginalNodeNumbers"));
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122

    if (origNodes)
    {
        int *on = origNodes->GetPointer(0);
        int nc = origNodes->GetNumberOfComponents();
        int n = origNodes->GetNumberOfTuples() *nc;
        int comp = nc -1;
        for (int i = comp; i < n; i+=nc )
        {
            int id = i / nc;
            if (on[i] == orig && group->IsId(id) == -1)
                group->InsertNextId(id);
        }
    }
}