/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/

#ifndef mitkPlanarSubdivisionPolygon_h
#define mitkPlanarSubdivisionPolygon_h

#include <mitkPlanarFigure.h>
#include <mitkPlanarPolygon.h>
#include <MitkPlanarFigureExports.h>

namespace mitk
{
  class PlaneGeometry;

  /**
   * \brief Implementation of PlanarFigure representing a subdivision polygon (smooth curve).
   *
   * A subdivision polygon uses iterative subdivision to produce a smooth
   * curve from the control points. The number of subdivision rounds and a
   * tension parameter control the smoothness of the resulting curve.
   *
   * Inherits circumference and area features from PlanarPolygon. The
   * polyline is generated by applying multiple rounds of subdivision to the
   * control points.
   *
   * \sa PlanarPolygon, PlanarBezierCurve, PlanarFigureMapper2D
   */
  class MITKPLANARFIGURE_EXPORT PlanarSubdivisionPolygon : public PlanarPolygon
  {
  public:
    mitkClassMacro(PlanarSubdivisionPolygon, PlanarPolygon);

    itkFactorylessNewMacro(Self);

    itkCloneMacro(Self);

      /** \brief Returns 3 -- a subdivision polygon requires at least three control points. */
      unsigned int GetMinimumNumberOfControlPoints() const override
    {
      return 3;
    }

    /** \brief Returns 1000 -- control points are practically unlimited. */
    unsigned int GetMaximumNumberOfControlPoints() const override { return 1000; }

    /**
     * \brief Returns the number of subdivision rounds applied during polyline generation.
     * \return The current number of subdivision rounds.
     */
    unsigned int GetSubdivisionRounds() const { return m_SubdivisionRounds; }

    /**
     * \brief Sets the number of subdivision rounds.
     *
     * More rounds produce a smoother curve but increase the number of polyline points.
     *
     * \param[in] subdivisionRounds The number of subdivision rounds.
     */
    void SetSubdivisionRounds(int subdivisionRounds) { m_SubdivisionRounds = subdivisionRounds; }

    /**
     * \brief Returns the control point index that corresponds to a given polyline point.
     *
     * \param[in] indexOfPolylinePoint Index of the polyline point.
     * \param[in] polyLineIndex        Index of the polyline.
     * \return The index of the corresponding control point, or -1 if none matches.
     */
    int GetControlPointForPolylinePoint(int indexOfPolylinePoint, int polyLineIndex) const override;

    /**
     * \brief Returns the tension parameter for the subdivision algorithm.
     *
     * The higher the tension parameter, the lower the "tension" on the control
     * points. Valid range: 0 < w_tension < 0.1. A value of 0.0625 (1/16) is
     * a good default.
     *
     * \return The current tension parameter.
     */
    float GetTensionParameter() const { return m_TensionParameter; }

    /**
     * \brief Sets the tension parameter for the subdivision algorithm.
     * \param[in] tensionParameter The tension parameter value.
     */
    void SetTensionParameter(float tensionParameter) { m_TensionParameter = tensionParameter; }

    /**
     * \brief Checks for intersections of a line segment with the subdivision polygon edges.
     *
     * \param[in] p1 Start point of the test line segment.
     * \param[in] p2 End point of the test line segment.
     * \return A vector of intersection points.
     */
    std::vector<mitk::Point2D> CheckForLineIntersection(const Point2D &p1, const Point2D &p2) const;

    /** \brief Increases the number of subdivision rounds by one. */
    void IncreaseSubdivisions();
    /** \brief Decreases the number of subdivision rounds by one (minimum 1). */
    void DecreaseSubdivisions();

    /**
     * \brief Compares this PlanarSubdivisionPolygon with another PlanarFigure for equality.
     * \param[in] other The PlanarFigure to compare with.
     * \return True if both figures are considered equal.
     */
    bool Equals(const mitk::PlanarFigure &other) const override;

  protected:
    PlanarSubdivisionPolygon();
    PlanarSubdivisionPolygon(const Self& other);

    mitkCloneMacro(Self);

    /** \brief Generates the poly-line representation of the planar figure. */
    void GeneratePolyLine() override;

    float m_TensionParameter;
    int m_SubdivisionRounds;

  private:
  };

} // namespace mitk

#endif
