text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    vtkAlgorithm.h
  
    Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
    All rights reserved.
    See Copyright.txt or http://www.kitware.com/Copyright.htm 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.
  
  =========================================================================*/
  /**
   * @class   vtkAlgorithm
   * @brief   Superclass for all sources, filters, and sinks in VTK.
   *
   * vtkAlgorithm is the superclass for all sources, filters, and sinks
   * in VTK.  It defines a generalized interface for executing data
   * processing algorithms.  Pipeline connections are associated with
   * input and output ports that are independent of the type of data
   * passing through the connections.
   *
   * Instances may be used independently or within pipelines with a
   * variety of architectures and update mechanisms.  Pipelines are
   * controlled by instances of vtkExecutive.  Every vtkAlgorithm
   * instance has an associated vtkExecutive when it is used in a
   * pipeline.  The executive is responsible for data flow.
   */
  
  #ifndef vtkAlgorithm_h
  #define vtkAlgorithm_h
  
  #include "vtkCommonExecutionModelModule.h" // For export macro
  #include "vtkObject.h"
  
  class vtkAbstractArray;
  class vtkAlgorithmInternals;
  class vtkAlgorithmOutput;
  class vtkCollection;
  class vtkDataArray;
  class vtkDataObject;
  class vtkExecutive;
  class vtkInformation;
  class vtkInformationInformationVectorKey;
  class vtkInformationIntegerKey;
  class vtkInformationStringKey;
  class vtkInformationStringVectorKey;
  class vtkInformationVector;
  class vtkProgressObserver;
  
  class VTKCOMMONEXECUTIONMODEL_EXPORT vtkAlgorithm : public vtkObject
  {
  public:
    static vtkAlgorithm* New();
    vtkTypeMacro(vtkAlgorithm, vtkObject);
    void PrintSelf(ostream& os, vtkIndent indent) override;
  
    /**
     * Values used for setting the desired output precision for various
     * algorithms. Currently, the following algorithms support changing their
     * output precision: vtkAppendPolyData, vtkCleanPolyData, vtkClipPolyData,
     * vtkConnectivityFilter, vtkDecimatePolylineFilter, vtkDecimatePro, vtkDelaunay3D,
     * vtkFeatureEdges, vtkGlyph3D, vtkHedgeHog, vtkMaskPoints, vtkPolyDataConnectivityFilter,
     * vtkSmoothPolyDataFilter, vtkStaticCleanPolyData, vtkThresholdPoints, vtkTubeFilter,
     * vtkAppendPoints, vtkTransformFilter, vtkTransformPolyDataFilter,
     * vtkLinearToQuadraticCellsFilter, vtkProcrustesAlignmentFilter,
     * vtkAdaptiveSubdivisionFilter, vtkBoundedPointSource, vtkArcSource, vtkConeSource,
     * vtkCubeSource, vtkCylinderSource, vtkDiskSource, vtkEllipseArcSource,
     * vtkEllipticalButtonSource, vtkFrustumSource, vtkGlyphSource2D, vtkLineSource,
     * vtkOutlineSource, vtkParametricFunctionSource, vtkPlaneSource, vtkPlatonicSolidSource,
     * vtkPointSource, vtkRectangularButtonSource, vtkRegularPolygonSource, vtkSphereSource,
     * vtkSuperquadricSource, vtkTessellatedBoxSource, vtkTextSource, vtkTexturedSphereSource,
     * vtkImageToPoints, vtkDepthImageToPointCloud.
     * SINGLE_PRECISION - Output single-precision floating-point (i.e. float)
     * DOUBLE_PRECISION - Output double-precision floating-point (i.e. double)
     * DEFAULT_PRECISION - Output precision should match the input precision.
     */
    enum DesiredOutputPrecision
    {
      SINGLE_PRECISION,
      DOUBLE_PRECISION,
      DEFAULT_PRECISION
    };
  
    /**
     * Check whether this algorithm has an assigned executive.  This
     * will NOT create a default executive.
     */
    int HasExecutive();
  
    /**
     * Get this algorithm's executive.  If it has none, a default
     * executive will be created.
     */
    vtkExecutive* GetExecutive();
  
    /**
     * Set this algorithm's executive.  This algorithm is removed from
     * any executive to which it has previously been assigned and then
     * assigned to the given executive.
     */
    virtual void SetExecutive(vtkExecutive* executive);
  
    /**
     * Upstream/Downstream requests form the generalized interface
     * through which executives invoke a algorithm's functionality.
     * Upstream requests correspond to information flow from the
     * algorithm's outputs to its inputs.  Downstream requests
     * correspond to information flow from the algorithm's inputs to its
     * outputs.
  
     * A downstream request is defined by the contents of the request
     * information object.  The input to the request is stored in the
     * input information vector passed to ProcessRequest.  The results
     * of an downstream request are stored in the output information
     * vector passed to ProcessRequest.
  
     * An upstream request is defined by the contents of the request
     * information object.  The input to the request is stored in the
     * output information vector passed to ProcessRequest.  The results
     * of an upstream request are stored in the input information vector
     * passed to ProcessRequest.
  
     * It returns the boolean status of the pipeline (false
     * means failure).
     */
    virtual vtkTypeBool ProcessRequest(
      vtkInformation* request, vtkInformationVector** inInfo, vtkInformationVector* outInfo);
  
    /**
     * Version of ProcessRequest() that is wrapped. This converts the
     * collection to an array and calls the other version.
     */
    vtkTypeBool ProcessRequest(
      vtkInformation* request, vtkCollection* inInfo, vtkInformationVector* outInfo);
  
    /**
     * A special version of ProcessRequest meant specifically for the
     * pipeline modified time request.  See
     * vtkExecutive::ComputePipelineMTime() for details.
     */
    virtual int ComputePipelineMTime(vtkInformation* request, vtkInformationVector** inInfoVec,
      vtkInformationVector* outInfoVec, int requestFromOutputPort, vtkMTimeType* mtime);
  
    /**
     * This method gives the algorithm a chance to modify the contents of a
     * request before or after (specified in the when argument) it is
     * forwarded. The default implementation is empty. Returns 1 on success,
     * 0 on failure. When can be either vtkExecutive::BeforeForward or
     * vtkExecutive::AfterForward.
     */
    virtual int ModifyRequest(vtkInformation* request, int when);
  
    /**
     * Get the information object associated with an input port.  There
     * is one input port per kind of input to the algorithm.  Each input
     * port tells executives what kind of data and downstream requests
     * this algorithm can handle for that input.
     */
    vtkInformation* GetInputPortInformation(int port);
  
    /**
     * Get the information object associated with an output port.  There
     * is one output port per output from the algorithm.  Each output
     * port tells executives what kind of upstream requests this
     * algorithm can handle for that output.
     */
    vtkInformation* GetOutputPortInformation(int port);
  
    ///@{
    /**
     * Set/Get the information object associated with this algorithm.
     */
    vtkGetObjectMacro(Information, vtkInformation);
    virtual void SetInformation(vtkInformation*);
    ///@}
  
    /**
     * Get the number of input ports used by the algorithm.
     */
    int GetNumberOfInputPorts();
  
    /**
     * Get the number of output ports provided by the algorithm.
     */
    int GetNumberOfOutputPorts();
  
    ///@{
    /**
     * Participate in garbage collection.
     */
    bool UsesGarbageCollector() const override { return true; }
    ///@}
  
    ///@{
    /**
     * Set/Get the AbortExecute flag for the process object. Process objects
     * may handle premature termination of execution in different ways.
     */
    vtkSetMacro(AbortExecute, vtkTypeBool);
    vtkGetMacro(AbortExecute, vtkTypeBool);
    vtkBooleanMacro(AbortExecute, vtkTypeBool);
    ///@}
  
    ///@{
    /**
     * Get the execution progress of a process object.
     */
    vtkGetMacro(Progress, double);
    ///@}
  
    /**
     * Update the progress of the process object. If a ProgressMethod exists,
     * executes it.  Then set the Progress ivar to amount. The parameter amount
     * should range between (0,1).
     */
    void UpdateProgress(double amount);
  
    ///@{
    /**
     * Specify the shift and scale values to use to apply to the progress amount
     * when `UpdateProgress` is called. By default shift is set to 0, and scale is
     * set to 1.0. This is useful when the vtkAlgorithm instance is used as an
     * internal algorithm to solve only a part of a whole problem.
     *
     * If calling on a internal vtkAlgorithm, make sure you take into
     * consideration that values set of the outer vtkAlgorithm as well since the
     * outer vtkAlgorithm itself may be nested in another algorithm.
     *
     * @note SetProgressShiftScale does not modify the MTime of the algorithm.
     */
    void SetProgressShiftScale(double shift, double scale);
    vtkGetMacro(ProgressShift, double);
    vtkGetMacro(ProgressScale, double);
    ///@}
  
    ///@{
    /**
     * Set the current text message associated with the progress state.
     * This may be used by a calling process/GUI.
     * Note: Because SetProgressText() is called from inside RequestData()
     * it does not modify the algorithm object. Algorithms are not
     * allowed to modify themselves from inside RequestData().
     */
    void SetProgressText(const char* ptext);
    vtkGetStringMacro(ProgressText);
    ///@}
  
    ///@{
    /**
     * The error code contains a possible error that occurred while
     * reading or writing the file.
     */
    vtkGetMacro(ErrorCode, unsigned long);
    ///@}
  
    // left public for performance since it is used in inner loops
    vtkTypeBool AbortExecute;
  
    /**
     * Keys used to specify input port requirements.
     * \ingroup InformationKeys
     */
    static vtkInformationIntegerKey* INPUT_IS_OPTIONAL();
    /**
     * \ingroup InformationKeys
     */
    static vtkInformationIntegerKey* INPUT_IS_REPEATABLE();
    /**
     * \ingroup InformationKeys
     */
    static vtkInformationInformationVectorKey* INPUT_REQUIRED_FIELDS();
    /**
     * \ingroup InformationKeys
     */
    static vtkInformationStringVectorKey* INPUT_REQUIRED_DATA_TYPE();
    /**
     * \ingroup InformationKeys
     */
    static vtkInformationInformationVectorKey* INPUT_ARRAYS_TO_PROCESS();
    /**
     * \ingroup InformationKeys
     */
    static vtkInformationIntegerKey* INPUT_PORT();
    /**
     * \ingroup InformationKeys
     */
    static vtkInformationIntegerKey* INPUT_CONNECTION();
  
    /**
     * This key tells the executive that a particular output port
     * is capable of producing an arbitrary subextent of the whole
     * extent. Many image sources and readers fall into this category
     * but some such as the legacy structured data readers cannot
     * support this feature.
     * \ingroup InformationKeys
     */
    static vtkInformationIntegerKey* CAN_PRODUCE_SUB_EXTENT();
  
    /**
     * Key that tells the pipeline that a particular algorithm
     * can or cannot handle piece request. If a filter cannot handle
     * piece requests and is asked for a piece, the executive will
     * flag an error. If a structured data source cannot handle piece
     * requests but can produce sub-extents (CAN_PRODUCE_SUB_EXTENT),
     * the executive will use an extent translator to split the extent
     * into pieces. Otherwise, if a source cannot handle piece requests,
     * the executive will ask for the whole data for piece 0 and not
     * execute the source for other pieces.
     * \ingroup InformationKeys
     */
    static vtkInformationIntegerKey* CAN_HANDLE_PIECE_REQUEST();
  
    ///@{
    /**
     * Set the input data arrays that this algorithm will
     * process. Specifically the idx array that this algorithm will process
     * (starting from 0) is the array on port, connection with the specified
     * association and name or attribute type (such as SCALARS). The
     * fieldAssociation refers to which field in the data object the array is
     * stored. See vtkDataObject::FieldAssociations for detail.
     */
    virtual void SetInputArrayToProcess(
      int idx, int port, int connection, int fieldAssociation, const char* name);
    virtual void SetInputArrayToProcess(
      int idx, int port, int connection, int fieldAssociation, int fieldAttributeType);
    virtual void SetInputArrayToProcess(int idx, vtkInformation* info);
    ///@}
  
    /**
     * String based versions of SetInputArrayToProcess(). Because
     * fieldAssociation and fieldAttributeType are enums, they cannot be
     * easily accessed from scripting language. These methods provides an
     * easy and safe way of passing association and attribute type
     * information. Field association is one of the following:
     * @verbatim
     * vtkDataObject::FIELD_ASSOCIATION_POINTS
     * vtkDataObject::FIELD_ASSOCIATION_CELLS
     * vtkDataObject::FIELD_ASSOCIATION_NONE
     * vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS
     * @endverbatim
     * Attribute type is one of the following:
     * @verbatim
     * vtkDataSetAttributes::SCALARS
     * vtkDataSetAttributes::VECTORS
     * vtkDataSetAttributes::NORMALS
     * vtkDataSetAttributes::TCOORDS
     * vtkDataSetAttributes::TENSORS
     * @endverbatim
     * If the last argument is not an attribute type, it is assumed to
     * be an array name.
     */
    virtual void SetInputArrayToProcess(int idx, int port, int connection,
      const char* fieldAssociation, const char* attributeTypeorName);
  
    /**
     * Get the info object for the specified input array to this algorithm
     */
    vtkInformation* GetInputArrayInformation(int idx);
  
    // from here down are convenience methods that really are executive methods
  
    /**
     * Remove all the input data.
     */
    void RemoveAllInputs();
  
    /**
     * Get the data object that will contain the algorithm output for
     * the given port.
     */
    vtkDataObject* GetOutputDataObject(int port);
  
    /**
     * Get the data object that will contain the algorithm input for the given
     * port and given connection.
     */
    vtkDataObject* GetInputDataObject(int port, int connection);
  
    ///@{
    /**
     * Set the connection for the given input port index.  Each input
     * port of a filter has a specific purpose.  A port may have zero or
     * more connections and the required number is specified by each
     * filter.  Setting the connection with this method removes all
     * other connections from the port.  To add more than one connection
     * use AddInputConnection().
  
     * The input for the connection is the output port of another
     * filter, which is obtained with GetOutputPort().  Typical usage is
  
     * filter2->SetInputConnection(0, filter1->GetOutputPort(0)).
     */
    virtual void SetInputConnection(int port, vtkAlgorithmOutput* input);
    virtual void SetInputConnection(vtkAlgorithmOutput* input);
    ///@}
  
    ///@{
    /**
     * Add a connection to the given input port index.  See
     * SetInputConnection() for details on input connections.  This
     * method is the complement to RemoveInputConnection() in that it
     * adds only the connection specified without affecting other
     * connections.  Typical usage is
  
     * filter2->AddInputConnection(0, filter1->GetOutputPort(0)).
     */
    virtual void AddInputConnection(int port, vtkAlgorithmOutput* input);
    virtual void AddInputConnection(vtkAlgorithmOutput* input);
    ///@}
  
    /**
     * Remove a connection from the given input port index.  See
     * SetInputConnection() for details on input connection.  This
     * method is the complement to AddInputConnection() in that it
     * removes only the connection specified without affecting other
     * connections.  Typical usage is
  
     * filter2->RemoveInputConnection(0, filter1->GetOutputPort(0)).
     */
    virtual void RemoveInputConnection(int port, vtkAlgorithmOutput* input);
  
    /**
     * Remove a connection given by index idx.
     */
    virtual void RemoveInputConnection(int port, int idx);
  
    /**
     * Removes all input connections.
     */
    virtual void RemoveAllInputConnections(int port);
  
    /**
     * Sets the data-object as an input on the given port index. Setting the input with
     * this method removes all other connections from the port. Internally, this
     * method creates a vtkTrivialProducer instance and sets that as the
     * input-connection for the given port. It is safe to call this method repeatedly
     * with the same input data object. The MTime of the vtkAlgorithm will not
     * change unless the data object changed.
     */
    virtual void SetInputDataObject(int port, vtkDataObject* data);
    virtual void SetInputDataObject(vtkDataObject* data) { this->SetInputDataObject(0, data); }
  
    /**
     * Add the data-object as an input to this given port. This will add a new
     * input connection on the specified port without affecting any existing
     * connections on the same input port.
     */
    virtual void AddInputDataObject(int port, vtkDataObject* data);
    virtual void AddInputDataObject(vtkDataObject* data) { this->AddInputDataObject(0, data); }
  
    /**
     * Get a proxy object corresponding to the given output port of this
     * algorithm.  The proxy object can be passed to another algorithm's
     * SetInputConnection(), AddInputConnection(), and
     * RemoveInputConnection() methods to modify pipeline connectivity.
     */
    vtkAlgorithmOutput* GetOutputPort(int index);
    vtkAlgorithmOutput* GetOutputPort() { return this->GetOutputPort(0); }
  
    /**
     * Get the number of inputs currently connected to a port.
     */
    int GetNumberOfInputConnections(int port);
  
    /**
     * Get the total number of inputs for this algorithm
     */
    int GetTotalNumberOfInputConnections();
  
    /**
     * Get the algorithm output port connected to an input port.
     */
    vtkAlgorithmOutput* GetInputConnection(int port, int index);
  
    /**
     * Returns the algorithm and the output port index of
     * that algorithm connected to a port-index pair.
     */
    vtkAlgorithm* GetInputAlgorithm(int port, int index, int& algPort);
  
    /**
     * Returns the algorithm connected to a port-index pair.
     */
    vtkAlgorithm* GetInputAlgorithm(int port, int index);
  
    /**
     * Equivalent to GetInputAlgorithm(0, 0).
     */
    vtkAlgorithm* GetInputAlgorithm() { return this->GetInputAlgorithm(0, 0); }
  
    /**
     * Returns the executive associated with a particular input
     * connection.
     */
    vtkExecutive* GetInputExecutive(int port, int index);
  
    /**
     * Equivalent to GetInputExecutive(0, 0)
     */
    vtkExecutive* GetInputExecutive() { return this->GetInputExecutive(0, 0); }
  
    /**
     * Return the information object that is associated with
     * a particular input connection. This can be used to get
     * meta-data coming from the REQUEST_INFORMATION pass and set
     * requests for the REQUEST_UPDATE_EXTENT pass. NOTE:
     * Do not use this in any of the pipeline passes. Use
     * the information objects passed as arguments instead.
     */
    vtkInformation* GetInputInformation(int port, int index);
  
    /**
     * Equivalent to GetInputInformation(0, 0)
     */
    vtkInformation* GetInputInformation() { return this->GetInputInformation(0, 0); }
  
    /**
     * Return the information object that is associated with
     * a particular output port. This can be used to set
     * meta-data coming during the REQUEST_INFORMATION. NOTE:
     * Do not use this in any of the pipeline passes. Use
     * the information objects passed as arguments instead.
     */
    vtkInformation* GetOutputInformation(int port);
  
    ///@{
    /**
     * Bring this algorithm's outputs up-to-date.
     */
    virtual void Update(int port);
    virtual void Update();
    ///@}
  
    /**
     * This method enables the passing of data requests to the algorithm
     * to be used during execution (in addition to bringing a particular
     * port up-to-date). The requests argument should contain an information
     * object for each port that requests need to be passed. For each
     * of those, the pipeline will copy all keys to the output information
     * before execution. This is equivalent to:
     * \verbatim
     * algorithm->UpdateInformation();
     * for (int i=0; i<algorithm->GetNumberOfOutputPorts(); i++)
     * {
     * vtkInformation* portRequests = requests->GetInformationObject(i);
     * if (portRequests)
     * {
     * algorithm->GetOutputInformation(i)->Append(portRequests);
     * }
     * }
     * algorithm->Update();
     * \endverbatim
     * Available requests include UPDATE_PIECE_NUMBER(), UPDATE_NUMBER_OF_PIECES()
     * UPDATE_EXTENT() etc etc.
     */
    virtual vtkTypeBool Update(int port, vtkInformationVector* requests);
  
    /**
     * Convenience method to update an algorithm after passing requests
     * to its first output port. See documentation for
     * Update(int port, vtkInformationVector* requests) for details.
     */
    virtual vtkTypeBool Update(vtkInformation* requests);
  
    /**
     * Convenience method to update an algorithm after passing requests
     * to its first output port. See documentation for
     * Update(int port, vtkInformationVector* requests) for details.
     * Supports piece and extent (optional) requests.
     */
    virtual int UpdatePiece(
      int piece, int numPieces, int ghostLevels, const int extents[6] = nullptr);
  
    /**
     * Convenience method to update an algorithm after passing requests
     * to its first output port.
     * Supports extent request.
     */
    virtual int UpdateExtent(const int extents[6]);
  
    /**
     * Convenience method to update an algorithm after passing requests
     * to its first output port. See documentation for
     * Update(int port, vtkInformationVector* requests) for details.
     * Supports time, piece (optional) and extent (optional) requests.
     */
    virtual int UpdateTimeStep(double time, int piece = -1, int numPieces = 1, int ghostLevels = 0,
      const int extents[6] = nullptr);
  
    /**
     * Bring the algorithm's information up-to-date.
     */
    virtual void UpdateInformation();
  
    /**
     * Create output object(s).
     */
    virtual void UpdateDataObject();
  
    /**
     * Propagate meta-data upstream.
     */
    virtual void PropagateUpdateExtent();
  
    /**
     * Bring this algorithm's outputs up-to-date.
     */
    virtual void UpdateWholeExtent();
  
    /**
     * Convenience routine to convert from a linear ordering of input
     * connections to a port/connection pair.
     */
    void ConvertTotalInputToPortConnection(int ind, int& port, int& conn);
  
    //======================================================================
    // The following block of code is to support old style VTK applications. If
    // you are using these calls there are better ways to do it in the new
    // pipeline
    //======================================================================
  
    ///@{
    /**
     * Turn release data flag on or off for all output ports.
     */
    virtual void SetReleaseDataFlag(int);
    virtual int GetReleaseDataFlag();
    void ReleaseDataFlagOn();
    void ReleaseDataFlagOff();
    ///@}
  
    //========================================================================
  
    ///@{
    /**
     * This detects when the UpdateExtent will generate no data
     * This condition is satisfied when the UpdateExtent has
     * zero volume (0,-1,...) or the UpdateNumberOfPieces is 0.
     * The source uses this call to determine whether to call Execute.
     */
    int UpdateExtentIsEmpty(vtkInformation* pinfo, vtkDataObject* output);
    int UpdateExtentIsEmpty(vtkInformation* pinfo, int extentType);
    ///@}
  
    /**
     * If the DefaultExecutivePrototype is set, a copy of it is created
     * in CreateDefaultExecutive() using NewInstance().
     */
    static void SetDefaultExecutivePrototype(vtkExecutive* proto);
  
    ///@{
    /**
     * These functions return the update extent for output ports that
     * use 3D extents. Where port is not specified, it is assumed to
     * be 0.
     */
    int* GetUpdateExtent() VTK_SIZEHINT(6) { return this->GetUpdateExtent(0); }
    int* GetUpdateExtent(int port) VTK_SIZEHINT(6);
    void GetUpdateExtent(int& x0, int& x1, int& y0, int& y1, int& z0, int& z1)
    {
      this->GetUpdateExtent(0, x0, x1, y0, y1, z0, z1);
    }
    void GetUpdateExtent(int port, int& x0, int& x1, int& y0, int& y1, int& z0, int& z1);
    void GetUpdateExtent(int extent[6]) { this->GetUpdateExtent(0, extent); }
    void GetUpdateExtent(int port, int extent[6]);
    ///@}
  
    ///@{
    /**
     * These functions return the update extent for output ports that
     * use piece extents. Where port is not specified, it is assumed to
     * be 0.
     */
    int GetUpdatePiece() { return this->GetUpdatePiece(0); }
    int GetUpdatePiece(int port);
    int GetUpdateNumberOfPieces() { return this->GetUpdateNumberOfPieces(0); }
    int GetUpdateNumberOfPieces(int port);
    int GetUpdateGhostLevel() { return this->GetUpdateGhostLevel(0); }
    int GetUpdateGhostLevel(int port);
    ///@}
  
    ///@{
    /**
     * If an ProgressObserver is set, the algorithm will report
     * progress through it rather than directly. This means that
     * it will call UpdateProgress() on the ProgressObserver rather
     * than itself report it and set progress.
     * This is most useful in situations where multiple threads
     * are executing an algorithm at the same time and want to
     * handle progress locally.
     */
    void SetProgressObserver(vtkProgressObserver*);
    vtkGetObjectMacro(ProgressObserver, vtkProgressObserver);
    ///@}
  
  protected:
    vtkAlgorithm();
    ~vtkAlgorithm() override;
  
    // Keys used to indicate that input/output port information has been
    // filled.
    static vtkInformationIntegerKey* PORT_REQUIREMENTS_FILLED();
  
    // Arbitrary extra information associated with this algorithm
    vtkInformation* Information;
  
    /**
     * Fill the input port information objects for this algorithm.  This
     * is invoked by the first call to GetInputPortInformation for each
     * port so subclasses can specify what they can handle.
     */
    virtual int FillInputPortInformation(int port, vtkInformation* info);
  
    /**
     * Fill the output port information objects for this algorithm.
     * This is invoked by the first call to GetOutputPortInformation for
     * each port so subclasses can specify what they can handle.
     */
    virtual int FillOutputPortInformation(int port, vtkInformation* info);
  
    /**
     * Set the number of input ports used by the algorithm.
     */
    virtual void SetNumberOfInputPorts(int n);
  
    /**
     * Set the number of output ports provided by the algorithm.
     */
    virtual void SetNumberOfOutputPorts(int n);
  
    // Helper methods to check input/output port index ranges.
    int InputPortIndexInRange(int index, const char* action);
    int OutputPortIndexInRange(int index, const char* action);
  
    /**
     * Get the assocition of the actual data array for the input array specified
     * by idx, this is only reasonable during the REQUEST_DATA pass.
     */
    int GetInputArrayAssociation(int idx, vtkInformationVector** inputVector);
  
    ///@{
    /**
     * Filters that have multiple connections on one port can use
     * this signature. This will override the connection id that the
     * user set in SetInputArrayToProcess() with the connection id
     * passed. This way, the user specifies one array to process and
     * that information is used to obtain arrays for all the connection
     * on the port with the appropriate connection id substituted.
     */
    int GetInputArrayAssociation(int idx, int connection, vtkInformationVector** inputVector);
    int GetInputArrayAssociation(int idx, vtkDataObject* input);
    ///@}
  
    ///@{
    /**
     * Get the actual data array for the input array specified by idx, this is
     * only reasonable during the REQUEST_DATA pass
     */
    vtkDataArray* GetInputArrayToProcess(int idx, vtkInformationVector** inputVector);
    vtkDataArray* GetInputArrayToProcess(
      int idx, vtkInformationVector** inputVector, int& association);
    ///@}
  
    ///@{
    /**
     * Filters that have multiple connections on one port can use
     * this signature. This will override the connection id that the
     * user set in SetInputArrayToProcess() with the connection id
     * passed. This way, the user specifies one array to process and
     * that information is used to obtain arrays for all the connection
     * on the port with the appropriate connection id substituted.
     */
    vtkDataArray* GetInputArrayToProcess(int idx, int connection, vtkInformationVector** inputVector);
    vtkDataArray* GetInputArrayToProcess(
      int idx, int connection, vtkInformationVector** inputVector, int& association);
    vtkDataArray* GetInputArrayToProcess(int idx, vtkDataObject* input);
    vtkDataArray* GetInputArrayToProcess(int idx, vtkDataObject* input, int& association);
    ///@}
  
    ///@{
    /**
     * Get the actual data array for the input array specified by idx, this is
     * only reasonable during the REQUEST_DATA pass
     */
    vtkAbstractArray* GetInputAbstractArrayToProcess(int idx, vtkInformationVector** inputVector);
    vtkAbstractArray* GetInputAbstractArrayToProcess(
      int idx, vtkInformationVector** inputVector, int& association);
    ///@}
  
    ///@{
    /**
     * Filters that have multiple connections on one port can use
     * this signature. This will override the connection id that the
     * user set in SetInputArrayToProcess() with the connection id
     * passed. This way, the user specifies one array to process and
     * that information is used to obtain arrays for all the connection
     * on the port with the appropriate connection id substituted.
     */
    vtkAbstractArray* GetInputAbstractArrayToProcess(
      int idx, int connection, vtkInformationVector** inputVector);
    vtkAbstractArray* GetInputAbstractArrayToProcess(
      int idx, int connection, vtkInformationVector** inputVector, int& association);
    vtkAbstractArray* GetInputAbstractArrayToProcess(int idx, vtkDataObject* input);
    vtkAbstractArray* GetInputAbstractArrayToProcess(int idx, vtkDataObject* input, int& association);
    ///@}
  
    /**
     * This method takes in an index (as specified in SetInputArrayToProcess)
     * and a pipeline information vector. It then finds the information about
     * input array idx and then uses that information to find the field
     * information from the relevant field in the pifo vector (as done by
     * vtkDataObject::GetActiveFieldInformation)
     */
    vtkInformation* GetInputArrayFieldInformation(int idx, vtkInformationVector** inputVector);
  
    /**
     * Create a default executive.
     * If the DefaultExecutivePrototype is set, a copy of it is created
     * in CreateDefaultExecutive() using NewInstance().
     * Otherwise, vtkStreamingDemandDrivenPipeline is created.
     */
    virtual vtkExecutive* CreateDefaultExecutive();
  
    ///@{
    /**
     * The error code contains a possible error that occurred while
     * reading or writing the file.
     */
    vtkSetMacro(ErrorCode, unsigned long);
    unsigned long ErrorCode;
    ///@}
  
    // Progress/Update handling
    double Progress;
    char* ProgressText;
  
    // Garbage collection support.
    void ReportReferences(vtkGarbageCollector*) override;
  
    // executive methods below
  
    /**
     * Replace the Nth connection on the given input port.  For use only
     * by this class and subclasses.  If this is used to store a nullptr
     * input then the subclass must be able to handle nullptr inputs in its
     * ProcessRequest method.
     */
    virtual void SetNthInputConnection(int port, int index, vtkAlgorithmOutput* input);
  
    /**
     * Set the number of input connections on the given input port.  For
     * use only by this class and subclasses.  If this is used to store
     * a nullptr input then the subclass must be able to handle nullptr inputs
     * in its ProcessRequest method.
     */
    virtual void SetNumberOfInputConnections(int port, int n);
  
    static vtkExecutive* DefaultExecutivePrototype;
  
    /**
     * These methods are used by subclasses to implement methods to
     * set data objects directly as input. Internally, they create
     * a vtkTrivialProducer that has the data object as output and
     * connect it to the algorithm.
     */
    void SetInputDataInternal(int port, vtkDataObject* input)
    {
      this->SetInputDataObject(port, input);
    }
    void AddInputDataInternal(int port, vtkDataObject* input)
    {
      this->AddInputDataObject(port, input);
    }
  
    vtkProgressObserver* ProgressObserver;
  
  private:
    vtkExecutive* Executive;
    vtkInformationVector* InputPortInformation;
    vtkInformationVector* OutputPortInformation;
    vtkAlgorithmInternals* AlgorithmInternal;
    static void ConnectionAdd(
      vtkAlgorithm* producer, int producerPort, vtkAlgorithm* consumer, int consumerPort);
    static void ConnectionRemove(
      vtkAlgorithm* producer, int producerPort, vtkAlgorithm* consumer, int consumerPort);
    static void ConnectionRemoveAllInput(vtkAlgorithm* consumer, int port);
    static void ConnectionRemoveAllOutput(vtkAlgorithm* producer, int port);
  
  private:
    vtkAlgorithm(const vtkAlgorithm&) = delete;
    void operator=(const vtkAlgorithm&) = delete;
  
    double ProgressShift;
    double ProgressScale;
  };
  
  #endif
  