//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================
#include "pqCMBLIDARPieceObject.h"


#include "pqApplicationCore.h"
#include "pqObjectBuilder.h"
#include "pqPipelineRepresentation.h"
#include "pqPipelineSource.h"
#include "pqRenderView.h"
#include "pqSMAdaptor.h"
#include "vtkSMPVRepresentationProxy.h"
#include <vtkProcessModule.h>
#include <vtkSMDataSourceProxy.h>
#include <vtkSMIntVectorProperty.h>
#include <vtkSMPropertyHelper.h>
#include <vtkSMProxyManager.h>
#include "vtkSMProxyProperty.h"
#include <vtkSMRenderViewProxy.h>
#include <vtkSMRepresentationProxy.h>
#include <vtkSMSourceProxy.h>
#include "vtkSMRepresentationProxy.h"
#include "vtkGeometryRepresentation.h"
#include "vtkPVDataInformation.h"
#include "vtkTransform.h"

#include "pqRepresentationHelperFunctions.h"
#include "vtkDataObject.h"

#include <QTableWidgetItem>

//-----------------------------------------------------------------------------
pqCMBLIDARPieceObject::pqCMBLIDARPieceObject()
{
  this->init();
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::init()
{
  this->Source = NULL;
  this->DiggerSource = NULL;
  this->Representation = NULL;
  this->UseElevationFilter = false;
  this->FileName = "";
  this->PieceName = "";
  this->PieceIndex = 0;
  this->DisplayOnRatio = this->SaveOnRatio = 1;
  this->ReadOnRatio = -1;  // haven't read yet!
  this->TotalNumberOfPiecePoints = 0;
  this->NumberOfReadPoints = 0;
  this->NumberOfDisplayPointsEstimate = 0;
  this->NumberOfSavePointsEstimate = 0;
//  this->FileOffset = 0;
  this->Visibility = 1;
  this->Highlight = 0;
  this->ClipState = false;
  //this->Widget = NULL;
  this->HighlightColor[0] = 1.0;
  this->HighlightColor[1] = 0.0;
  this->HighlightColor[2] = 1.0;
  this->OriginalColor[0] = this->OriginalColor[1] = this->OriginalColor[2] = 1.0;

  this->ThresholdPosition[0] = 0.0;
  this->ThresholdPosition[1] = 0.0;
  this->ThresholdPosition[2] = 0.0;
  this->ThresholdOrientation[0] = 0.0;
  this->ThresholdOrientation[1] = 0.0;
  this->ThresholdOrientation[2] = 0.0;
  this->ThresholdScale[0] = 1.0;
  this->ThresholdScale[1] = 1.0;
  this->ThresholdScale[2] = 1.0;
  this->ThresholdOrigin[0] = 0.0;
  this->ThresholdOrigin[1] = 0.0;
  this->ThresholdOrigin[2] = 0.0;
}

//-----------------------------------------------------------------------------
pqCMBLIDARPieceObject::~pqCMBLIDARPieceObject()
{
  pqApplicationCore* core = pqApplicationCore::instance();
  pqObjectBuilder* builder = core->getObjectBuilder();

  if (this->Representation)
    {
    builder->destroy(this->Representation);
    this->Representation = NULL;
    }

  if (this->ElevationSource)
    {
    builder->destroy(this->ElevationSource);
    this->ElevationSource = NULL;
    }
  if (this->ThresholdSource)
    {
    builder->destroy(this->ThresholdSource);
    this->ThresholdSource = NULL;
    }
  if (this->DiggerSource)
    {
    builder->destroy(this->DiggerSource);
    this->DiggerSource = NULL;
    }
  if(this->ContourSource)
    {
    builder->destroy(this->ContourSource);
    this->ContourSource = NULL;
    }
  if (this->Source)
    {
    builder->destroy(this->Source);
    this->Source = NULL;
    }
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setDisplayOnRatio(int onRatio)
{
  if(onRatio > 0 && onRatio != this->DisplayOnRatio)
    {
    this->DisplayOnRatio = onRatio;
    }
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setSaveOnRatio(int onRatio)
{
  if(onRatio > 0 && onRatio != this->SaveOnRatio)
    {
    this->SaveOnRatio = onRatio;
    }
}


//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setReadOnRatio(int onRatio)
{
  if(onRatio > 0 && onRatio != this->ReadOnRatio)
    {
    this->ReadOnRatio = onRatio;
    }
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setRepresentation(pqDataRepresentation *rep)
{
  this->Representation = rep;
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setSource(pqPipelineSource *source)
{
  this->Source = source;
}

//-----------------------------------------------------------------------------
pqPipelineSource * pqCMBLIDARPieceObject::getSource() const
{
  return this->Source;
}
//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setThresholdSource(pqPipelineSource *thresholdSource)
{
  this->ThresholdSource = thresholdSource;
}

//-----------------------------------------------------------------------------
pqPipelineSource * pqCMBLIDARPieceObject::getThresholdSource() const
{
  return this->ThresholdSource;
}
//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setContourSource(pqPipelineSource *contourSource)
{
  this->ContourSource = contourSource;
}

//-----------------------------------------------------------------------------
pqPipelineSource * pqCMBLIDARPieceObject::getContourSource() const
{
  return this->ContourSource;
}

//-----------------------------------------------------------------------------
pqPipelineSource * pqCMBLIDARPieceObject::getDiggerSource() const
{
  return this->DiggerSource;
}

//-----------------------------------------------------------------------------
pqPipelineSource * pqCMBLIDARPieceObject::getElevationSource() const
{
  return this->ElevationSource;
}

//-----------------------------------------------------------------------------
pqDataRepresentation * pqCMBLIDARPieceObject::getRepresentation() const
{
  return this->Representation;
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setPieceIndex(int pieceIdx)
{
  this->PieceIndex = pieceIdx;
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setElevationFilterLowPoint(double *lowPoint)
{
  pqSMAdaptor::setMultipleElementProperty(
    this->ElevationSource->getProxy()->GetProperty("LowPoint"), 0, lowPoint[0]);
  pqSMAdaptor::setMultipleElementProperty(
    this->ElevationSource->getProxy()->GetProperty("LowPoint"), 1, lowPoint[1]);
  pqSMAdaptor::setMultipleElementProperty(
    this->ElevationSource->getProxy()->GetProperty("LowPoint"), 2, lowPoint[2]);
  this->ElevationSource->getProxy()->UpdateProperty("LowPoint", true);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setElevationFilterHighPoint(double *highPoint)
{
  pqSMAdaptor::setMultipleElementProperty(
    this->ElevationSource->getProxy()->GetProperty("HighPoint"), 0, highPoint[0]);
  pqSMAdaptor::setMultipleElementProperty(
    this->ElevationSource->getProxy()->GetProperty("HighPoint"), 1, highPoint[1]);
  pqSMAdaptor::setMultipleElementProperty(
    this->ElevationSource->getProxy()->GetProperty("HighPoint"), 2, highPoint[2]);
  this->ElevationSource->getProxy()->UpdateProperty("HighPoint", true);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::useElevationFilter(bool useElevation)
{
  if (useElevation == this->UseElevationFilter)
    {
    return;
    }

  this->UseElevationFilter = useElevation;
  if (!this->Highlight)
    {
    vtkSMPropertyHelper(this->Representation->getProxy(), "MapScalars").Set(0);
    RepresentationHelperFunctions::CMB_COLOR_REP_BY_ARRAY(this->Representation->getProxy(),
      useElevation ? "Elevation" : "Color", vtkDataObject::POINT, false);
    }
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::updateRepresentation()
{
  this->getContourSource()->updatePipeline();
  this->getThresholdSource()->updatePipeline();
  if (this->UseElevationFilter)
    {
    this->ElevationSource->updatePipeline();
    if (!this->Highlight)
      {
      RepresentationHelperFunctions::CMB_COLOR_REP_BY_ARRAY(
        this->Representation->getProxy(),
        "Elevation", vtkDataObject::POINT, false);
      }
    }
  this->Representation->getProxy()->UpdateVTKObjects();
}

//-----------------------------------------------------------------------------
pqCMBLIDARPieceObject *pqCMBLIDARPieceObject::createObject(pqPipelineSource* source,
                                                         double *bounds,
                                                         pqServer * /*server*/,
                                                         pqRenderView *view,
                                                         bool updateRep)
{
  pqApplicationCore* core = pqApplicationCore::instance();
  pqObjectBuilder* builder = core->getObjectBuilder();
  pqCMBLIDARPieceObject *obj = new pqCMBLIDARPieceObject();
  obj->Source = source;

  obj->ContourSource = builder->createFilter("filters","ClipPolygons",source);
  obj->DiggerSource = builder->createFilter("filters","ArcDepressFilter",obj->ContourSource);
  obj->ThresholdSource = builder->createFilter("filters","PointThresholdFilter",obj->DiggerSource);
  obj->ElevationSource = builder->createFilter("filters","LIDARElevationFilter", obj->ThresholdSource);
  // not initially viewing elevation output, but at least have filter set such
  // that sensible values are computed (the filter autmatically executes when
  // doing createDataRepresentation call)
  double minPt[3] = {0, 0, bounds[4]}, maxPt[3] = {0, 0, bounds[5]};
  obj->setElevationFilterLowPoint(minPt);
  obj->setElevationFilterHighPoint(maxPt);

  // force read
  vtkSMSourceProxy::SafeDownCast(obj->Source->getProxy() )->UpdatePipeline();

  obj->Representation =
    builder->createDataRepresentation(
    obj->ElevationSource->getOutputPort(0), view, "GeometryRepresentation");
  vtkSMPVRepresentationProxy::SafeDownCast(obj->Representation->getProxy())->SetRepresentationType("Point Gaussian");

  vtkSMPropertyHelper(obj->Representation->getProxy(), "GaussianRadius").Set(0);

  if (updateRep)
    {
    obj->Representation->getProxy()->UpdateVTKObjects();
    }

  vtkSMPropertyHelper(obj->Representation->getProxy(),
    "AmbientColor").Get(obj->OriginalColor, 3);

  // setup Origin for rotation
  double center[3];
  // only want up to 4 digits after the "."
  // (Note: really doing int(10000 * center) / 10000.0, where
  // center = (bounds[0] + bounds[1]) / 2.0,  but (10000 / 2.0) = 5000)
  center[0] = floor(5000 * (bounds[0] + bounds[1])) / 10000.0;
  center[1] = floor(5000 * (bounds[2] + bounds[3])) / 10000.0;
  center[2] = floor(5000 * (bounds[4] + bounds[5])) / 10000.0;
  //obj->setOrigin(center);
  vtkSMPropertyHelper(obj->Representation->getProxy(), "MapScalars").Set(0);
    RepresentationHelperFunctions::CMB_COLOR_REP_BY_ARRAY(
      obj->Representation->getProxy(),
      "Color", vtkDataObject::POINT, false);

  return obj;
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setLODMode(int mode, bool updateRep)
{
  vtkSMIntVectorProperty::SafeDownCast(this->Representation->
   getProxy()->GetProperty("SuppressLOD"))->SetElements1(mode);
  if (updateRep)
    {
    this->Representation->getProxy()->UpdateVTKObjects();
    }
}
//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::getBounds(double bounds[6]) const
{
  vtkSMRepresentationProxy::SafeDownCast(
    this->Representation->getProxy())->
    GetRepresentedDataInformation()->GetBounds(bounds);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::zoomOnObject()
{
  double bounds[6];
  this->getBounds(bounds);
  if (bounds[0] > bounds[1])
    {
    return; // if the bounds are invalid, don't change the camera
    }
  pqRenderView* renModule = qobject_cast<pqRenderView*>(
    this->Representation->getView());
  if (renModule)
    {
    vtkSMRenderViewProxy* rm = renModule->getRenderViewProxy();
    rm->ResetCamera(bounds);
    renModule->render();
    }
}

//----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setVisibility(int visible)
{
  if (this->Visibility != visible)
    {
    this->Visibility = visible;
    pqDataRepresentation* rep = this->Representation;

    rep->setVisible(visible);
    }
}

//----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setSelectionInput(vtkSMSourceProxy* selInput)
{
   vtkSMSourceProxy::SafeDownCast(this->getElevationSource() ?
    this->getElevationSource()->getProxy() : this->getSource()->getProxy())
    ->SetSelectionInput(0, selInput, 0);
}

//----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setHighlight(int highlight)
{
  if (this->Highlight != highlight)
    {
    this->Highlight = highlight;
    pqDataRepresentation* rep = this->Representation;

    if(highlight)
      {
      RepresentationHelperFunctions::CMB_COLOR_REP_BY_ARRAY(rep->getProxy(),
        NULL, vtkDataObject::POINT, false);
      vtkSMPropertyHelper(rep->getProxy(), "DiffuseColor").Set(
        this->HighlightColor, 3);
      vtkSMPropertyHelper(rep->getProxy(), "AmbientColor").Set(
        this->HighlightColor, 3);
      rep->getProxy()->UpdateVTKObjects();
      }
    else
      {
      vtkSMPropertyHelper(rep->getProxy(), "DiffuseColor").Set(
        this->OriginalColor, 3);
      vtkSMPropertyHelper(rep->getProxy(), "AmbientColor").Set(
        this->OriginalColor, 3);
      vtkSMPropertyHelper(rep->getProxy(), "MapScalars").Set(0);
      RepresentationHelperFunctions::CMB_COLOR_REP_BY_ARRAY(rep->getProxy(),
        this->UseElevationFilter ? "Elevation" : "Color", vtkDataObject::POINT, false);
      }
    }
}

//----------------------------------------------------------------------------
bool pqCMBLIDARPieceObject::isObjectUpToDate(bool clipEnabled,
                                            vtkBoundingBox &clipBBox)
{
  // is our clipping state up-to-date
  if (!this->isClipUpToDate(clipEnabled, clipBBox))
    {
    return false;
    }

  // is the display onRatio up-to-date
  if (this->DisplayOnRatio != this->ReadOnRatio)
    {
    return false;
    }

  return true;
}


//----------------------------------------------------------------------------
bool pqCMBLIDARPieceObject::isClipUpToDate(bool clipEnabled,
                                          vtkBoundingBox &clipBBox)
{
  // is our clipping state up-to-date
  if (clipEnabled != this->ClipState ||
    (clipEnabled && (!this->areClippingBoundsEqual(clipBBox) ||
    !this->isClipTransformationUnchanged())))
    {
    return false;
    }
  return true;
}

//-----------------------------------------------------------------------------
bool pqCMBLIDARPieceObject::isClipTransformationUnchanged()
{
  double position[3], scale[3], orientation[3], origin[3];
  this->getPosition(position);
  this->getOrientation(orientation);
  this->getOrigin(origin);
  this->getScale(scale);

  if (position[0] != this->ClipPosition[0] ||
    position[1] != this->ClipPosition[1] ||
    position[2] != this->ClipPosition[2] ||
    scale[0] != this->ClipScale[0] ||
    scale[1] != this->ClipScale[1] ||
    scale[2] != this->ClipScale[2] ||
    orientation[0] != this->ClipOrientation[0] ||
    orientation[1] != this->ClipOrientation[1] ||
    orientation[2] != this->ClipOrientation[2] ||
    ((origin[0] != this->ClipOrigin[0] ||
    origin[1] != this->ClipOrigin[1] ||
    origin[2] != this->ClipOrigin[2]) &&
    (orientation[0] != 0 || orientation[1] != 0 || orientation[2] != 0)))
    {
    return false;
    }
  return true;
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::saveClipPosition()
{
  vtkSMPropertyHelper(this->Representation->getProxy(),
                      "Position").Get(this->ClipPosition, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::saveClipOrientation()
{
  vtkSMPropertyHelper(this->Representation->getProxy(),
                      "Orientation").Get(this->ClipOrientation, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::saveClipScale()
{
  vtkSMPropertyHelper(this->Representation->getProxy(),
                      "Scale").Get(this->ClipScale, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::saveClipOrigin()
{
  vtkSMPropertyHelper(this->Representation->getProxy(),
                      "Origin").Get(this->ClipOrigin, 3);
}

//-----------------------------------------------------------------------------
bool pqCMBLIDARPieceObject::isThresholdTransformationUnchanged()
{
  double position[3], scale[3], orientation[3], origin[3];
  this->getPosition(position);
  this->getOrientation(orientation);
  this->getOrigin(origin);
  this->getScale(scale);

  if (position[0] != this->ThresholdPosition[0] ||
    position[1] != this->ThresholdPosition[1] ||
    position[2] != this->ThresholdPosition[2] ||
    scale[0] != this->ThresholdScale[0] ||
    scale[1] != this->ThresholdScale[1] ||
    scale[2] != this->ThresholdScale[2] ||
    orientation[0] != this->ThresholdOrientation[0] ||
    orientation[1] != this->ThresholdOrientation[1] ||
    orientation[2] != this->ThresholdOrientation[2] ||
    ((origin[0] != this->ThresholdOrigin[0] ||
    origin[1] != this->ThresholdOrigin[1] ||
    origin[2] != this->ThresholdOrigin[2]) &&
    (orientation[0] != 0 || orientation[1] != 0 || orientation[2] != 0)))
    {
    return false;
    }
  return true;
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::saveThresholdPosition()
{
  vtkSMPropertyHelper(this->Representation->getProxy(),
                      "Position").Get(this->ThresholdPosition, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::saveThresholdOrientation()
{
  vtkSMPropertyHelper(this->Representation->getProxy(),
                      "Orientation").Get(this->ThresholdOrientation, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::saveThresholdScale()
{
  vtkSMPropertyHelper(this->Representation->getProxy(),
                      "Scale").Get(this->ThresholdScale, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::saveThresholdOrigin()
{
  vtkSMPropertyHelper(this->Representation->getProxy(),
                      "Origin").Get(this->ThresholdOrigin, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::getPosition(double pos[3]) const
{
  vtkSMPropertyHelper(this->Representation->getProxy(), "Position").Get(pos, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setPosition(double pos[3], bool updateRep/*=true*/)
{
  vtkSMPropertyHelper(this->Representation->getProxy(), "Position").Set(pos, 3);
  if(updateRep)
    {
    this->Representation->getProxy()->UpdateVTKObjects();
    }
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::getOrientation(double ori[3]) const
{
  vtkSMPropertyHelper(this->Representation->getProxy(), "Orientation").Get(ori, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setOrientation(double ori[3], bool updateRep/*=true*/)
{
  vtkSMPropertyHelper(this->Representation->getProxy(), "Orientation").Set(ori, 3);
  if(updateRep)
    {
    this->Representation->getProxy()->UpdateVTKObjects();
    }
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::getScale(double scale[3]) const
{
  vtkSMPropertyHelper(this->Representation->getProxy(), "Scale").Get(scale, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setScale(double scale[3], bool updateRep/*=true*/)
{
  vtkSMPropertyHelper(this->Representation->getProxy(), "Scale").Set(scale, 3);
  if(updateRep)
    {
    this->Representation->getProxy()->UpdateVTKObjects();
    }
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::getOrigin(double origin[3]) const
{
  vtkSMPropertyHelper(this->Representation->getProxy(), "Origin").Get(origin, 3);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setOrigin(double origin[3], bool updateRep/*=true*/)
{
  vtkSMPropertyHelper(this->Representation->getProxy(), "Origin").Set(origin, 3);
  if(updateRep)
    {
    this->Representation->getProxy()->UpdateVTKObjects();
    }
}

//-----------------------------------------------------------------------------
bool pqCMBLIDARPieceObject::isPieceTransformed()
{
  double position[3], scale[3], orientation[3];
  this->getPosition(position);
  this->getOrientation(orientation);
  this->getScale(scale);

  if (position[0] != 0 || position[1] != 0 || position[2] != 0 ||
    orientation[0] != 0 || orientation[1] != 0 || orientation[2] != 0 ||
    scale[0] != 1 || scale[1] != 1 || scale[2] != 1)
    {
    return true;
    }
  return false;
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::getTransform(vtkTransform *transform) const
{
  if (!transform)
    {
    return;
    }

  double position[3], scale[3], orientation[3], origin[3];
  this->getPosition(position);
  this->getOrientation(orientation);
  this->getOrigin(origin);
  this->getScale(scale);

  // build the transformation
  transform->Identity();
  transform->PreMultiply();
  transform->Translate( position[0] + origin[0],
    position[1] + origin[1],
    position[2] + origin[2] );
  transform->RotateZ( orientation[2] );
  transform->RotateX( orientation[0] );
  transform->RotateY( orientation[1] );
  transform->Scale( scale );
  transform->Translate( -origin[0], -origin[1], -origin[2] );
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::updateThresholdUseFilter(int idx, int useFilter)
{
  this->updateProxyProperty(
    this->getThresholdSource(), "SetUseFilter", idx, useFilter);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::updatePolygonUseFilter(int idx, int useFilter)
{
  this->updateProxyProperty(
    this->getContourSource(), "ClipApplyPolygon", idx, useFilter);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::updatePolygonInvert(int idx, int invert)
{
  this->updateProxyProperty(
    this->getContourSource(), "InsideOut", idx, invert);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::updateGroupInvert(int groupIdx, int invert)
{
  this->setActiveContourGroup(groupIdx);
  //this->updateProxyProperty(
  //  this->getContourSource(), "GroupInvert", !invert);

  pqSMAdaptor::setElementProperty(
    this->getContourSource()->getProxy()->GetProperty("GroupInvert"), !invert);
  this->getContourSource()->getProxy()->UpdateProperty("GroupInvert", true);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::updatePolygonROI(int idx, int roi)
{
  this->updateProxyProperty(
    this->getContourSource(), "ClipAsROI", idx, roi);
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::updateProxyProperty(
  pqPipelineSource* source, const char* name, int idx, int val)
{
  vtkSMSourceProxy* smSource = vtkSMSourceProxy::SafeDownCast(
    source->getProxy());
  // only need to do filter if it is "active" ("UseFilter" is true)
  pqSMAdaptor::setMultipleElementProperty(
    smSource->GetProperty(name), 0, idx);
  pqSMAdaptor::setMultipleElementProperty(
    smSource->GetProperty(name), 1, val);
  smSource->UpdateProperty(name, true);
  smSource->UpdatePipeline();
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::resetWithNoThresholds(bool update)
{
  vtkSMSourceProxy* currentThresholds = vtkSMSourceProxy::SafeDownCast(
    this->getThresholdSource()->getProxy());
  currentThresholds->UpdatePropertyInformation();
  int numFilters = pqSMAdaptor::getElementProperty(
      currentThresholds->GetProperty("NumberOfThresholdSets")).toInt();
  if(numFilters ==0)
    {
    return;
    }
  QList<QVariant> values;
  for(int i=0; i<numFilters; i++)
    {
    values << 0;
    }
  pqSMAdaptor::setMultipleElementProperty(
    currentThresholds->GetProperty("UseFilterForAll"), values);
  currentThresholds->UpdateVTKObjects();
  if(update)
    {
    this->updateRepresentation();
    }

}
//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::resetWithNoContours(bool update)
{
  pqPipelineSource* clipPoly= this->getContourSource();
  vtkSMProxyProperty* clipFunc = vtkSMProxyProperty::SafeDownCast(
    clipPoly->getProxy()->GetProperty("ClipPolygon"));
  int numFilters = clipFunc->GetNumberOfProxies();
  if(numFilters ==0)
    {
    return;
    }
  QList<QVariant> values;
  for(int i=0; i<numFilters; i++)
    {
    values << 0;
    }
  pqSMAdaptor::setMultipleElementProperty(
    clipPoly->getProxy()->GetProperty("ClipApplyPolygonForAll"), values);
  clipPoly->getProxy()->UpdateVTKObjects();
  if(update)
    {
    this->updateRepresentation();
    }
}

//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::addThreshold()
{
  vtkSMSourceProxy* thresholdSourceProxy = vtkSMSourceProxy::SafeDownCast(
    this->getThresholdSource()->getProxy());
  thresholdSourceProxy->Modified();
  thresholdSourceProxy->InvokeCommand("AddFilter");
}
//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::removeThreshold()
{
  vtkSMSourceProxy* thresholdSourceProxy = vtkSMSourceProxy::SafeDownCast(
    this->getThresholdSource()->getProxy());

  thresholdSourceProxy->Modified();
  thresholdSourceProxy->InvokeCommand("RemoveFilter");
  //After removing the filter select the 0th element
  pqSMAdaptor::setElementProperty(
    thresholdSourceProxy->GetProperty("SetActiveFilterIndex"), 0);
  thresholdSourceProxy->UpdateProperty("SetActiveFilterIndex", true);
  thresholdSourceProxy->UpdateVTKObjects();
  thresholdSourceProxy->UpdatePipeline();
}
//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::clearThresholds()
{
  vtkSMSourceProxy* thresholdSourceProxy = vtkSMSourceProxy::SafeDownCast(
    this->getThresholdSource()->getProxy());

  thresholdSourceProxy->Modified();
  thresholdSourceProxy->InvokeCommand("RemoveAllFilters");
  thresholdSourceProxy->UpdateVTKObjects();
  thresholdSourceProxy->UpdatePipeline();
}
//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::addContour(vtkSMProxy* implicitLoop)
{
  pqPipelineSource* clipPoly= this->getContourSource();
  vtkSMProxyProperty* clipFunc = vtkSMProxyProperty::SafeDownCast(
    clipPoly->getProxy()->GetProperty("ClipPolygon"));
  clipFunc->AddProxy(implicitLoop);
  clipPoly->getProxy()->UpdateVTKObjects();
  if(this->getVisibility())
    {
    clipPoly->updatePipeline();
    }
}
//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::removeContour(vtkSMProxy* implicitLoop)
{
  pqPipelineSource* clipPoly= this->getContourSource();
  vtkSMProxyProperty* clipFunc = vtkSMProxyProperty::SafeDownCast(
    clipPoly->getProxy()->GetProperty("ClipPolygon"));
  clipFunc->RemoveProxy(implicitLoop);
  clipPoly->getProxy()->UpdateVTKObjects();
  if(this->getVisibility())
    {
    clipPoly->updatePipeline();
    }
}
//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::clearContours()
{

  vtkSMProxy* clipPoly= this->getContourSource()->getProxy();
  //vtkSMProxyProperty* clipFunc = vtkSMProxyProperty::SafeDownCast(
  //  clipPoly->getProxy()->GetProperty("ClipPolygon"));
  //clipFunc->RemoveAllProxies();
  //clipPoly->getProxy()->UpdateVTKObjects();
  clipPoly->InvokeCommand("RemoveAllClipPolygons");
  clipPoly->UpdateVTKObjects();
  if(this->getVisibility())
    {
    this->getContourSource()->updatePipeline();
    }
}
//-----------------------------------------------------------------------------
bool pqCMBLIDARPieceObject::hasActiveFilters()
{
  this->getThresholdSource()->getProxy()->UpdatePropertyInformation();
  this->getContourSource()->getProxy()->UpdatePropertyInformation();
  if ( pqSMAdaptor::getElementProperty(this->getThresholdSource()->getProxy()->
      GetProperty("NumberOfActiveThresholdSets")).toInt() ||
      pqSMAdaptor::getElementProperty(this->getContourSource()->getProxy()->
      GetProperty("NumberOfActivePolygons")).toInt())
    {
    return true;
    }
  return false;
}
//-----------------------------------------------------------------------------
void pqCMBLIDARPieceObject::setActiveContourGroup(int groupId)
{
  vtkSMProxy* contourProxy = this->getContourSource()->getProxy();
  pqSMAdaptor::setElementProperty(
                                  contourProxy->GetProperty("ActiveGroupIndex"), groupId);
  contourProxy->UpdateProperty("ActiveGroupIndex", true);

}
