// Copyright (c) 2006,2007,2009,2011 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v5.6.2/Arrangement_on_surface_2/include/CGAL/IO/Fig_stream_Conic_arc_2.h $
// $Id: Fig_stream_Conic_arc_2.h 625848e6293 2021-10-04T13:21:47+02:00 Mael Rouxel-Labbé
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s)     : Ron Wein           <wein@post.tau.ac.il>

#ifndef CGAL_FIG_STREAM_CONIC_ARC_2_H
#define CGAL_FIG_STREAM_CONIC_ARC_2_H

#include <CGAL/license/Arrangement_on_surface_2.h>


#include <CGAL/IO/Fig_stream.h>
#include <list>

namespace CGAL {
namespace IO {

/*!
 * Write an x-monotone conic arc to a FIG stream.
 */
template <class Conic_traits>
static void _write_x_monotone_conic_arc
   (CGAL::Fig_stream<typename Conic_traits::Alg_kernel>& fs,
    const typename Conic_traits::X_monotone_curve_2&     cv)
{
  typedef typename Conic_traits::Alg_kernel  Alg_kernel;
  typedef typename Conic_traits::Algebraic   Algebraic;
  typedef typename Conic_traits::Point_2     Alg_point_2;
  typedef typename Alg_kernel::Segment_2     Alg_segment_2;

  if (cv.orientation() == CGAL::COLLINEAR)
  {
    // In case of a linear segment:
    Alg_segment_2   seg = Alg_segment_2 (cv.source(), cv.target());
    fs << seg;
  }
  else if (CGAL::compare (cv.r(), cv.s()) == CGAL::EQUAL &&
           CGAL::sign (cv.t()) == CGAL::ZERO)
  {
    // In case of a circular arc:
    Algebraic    x_mid = (cv.source().x() + cv.target().x()) / 2;
    Alg_point_2  q = Alg_point_2(x_mid, 0);
    Alg_point_2  p = cv.point_at_x (q);

    fs.write_circular_arc (cv.source(), p, cv.target());
  }
  else
  {
    // Represent the arc as a spline with 5 control points.
    Algebraic   x;
    Alg_point_2 q;
    Alg_point_2 cps[5];
    int         i;

    cps[0] = cv.source();
    for (i = 1; i <= 3; i++)
    {
      x = (cv.source().x()*(4 - i) + cv.target().x()*i) / 4;

      q = Alg_point_2(x, 0);
      cps[i] = cv.point_at_x (q);
    }
    cps[4] = cv.target();

    fs.write_spline (cps + 0, cps + 5, 1.0);
  }

  return;
}

/*!
 * Write a conic arc to a FIG stream.
 */
template <class Conic_traits>
void write_conic_arc
   (CGAL::Fig_stream<typename Conic_traits::Alg_kernel>& fs,
    const typename Conic_traits::Curve_2&                cv)
{
  typedef typename Conic_traits::X_monotone_curve_2   Conic_arc_2;

  // Subdivide the arc into x-monotone sub-arcs.
  Conic_traits           traits;
  std::list<Conic_arc_2> xcvs;

  traits.make_x_monotone_2_object() (cv,
                                     std::back_inserter(xcvs));

  // Write the x-monotone sub-arcs.
  typename std::list<Conic_arc_2>::iterator xit;

  for (xit = xcvs.begin(); xit != xcvs.end(); ++xit)
    _write_x_monotone_conic_arc<Conic_traits> (fs, *xit);

  return;
}

}} // namespace CGAL::IO

#endif
