/******************************************************************************
 * File:   ogrdxf_polyline_smooth.h
 *
 * Project:  Interpolation support for smooth POLYLINE and LWPOLYLINE entities.
 * Purpose:  Definition of classes for OGR .dxf driver.
 * Author:   TJ Snider, timsn@thtree.com
 *           Ray Gardener, Daylon Graphics Ltd.
 *
 ******************************************************************************
 * Copyright (c) 2010 Daylon Graphics Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 ****************************************************************************/

#ifndef OGRDXF_SMOOTH_POLYLINE_H_INCLUDED
#define OGRDXF_SMOOTH_POLYLINE_H_INCLUDED

#include "ogrsf_frmts.h"
#include "cpl_conv.h"
#include <vector>
#include "assert.h"

class DXFSmoothPolylineVertex
{
  public:
    double x;
    double y;
    double z;
    double bulge;

    DXFSmoothPolylineVertex()
    {
        x = y = z = bulge = 0.0;
    }

    DXFSmoothPolylineVertex(double dfX, double dfY, double dfZ, double dfBulge)
    {
        set(dfX, dfY, dfZ, dfBulge);
    }

    void set(double dfX, double dfY, double dfZ, double dfBulge)
    {
        x = dfX;
        y = dfY;
        z = dfZ;
        bulge = dfBulge;
    }

    void scale(double s)
    {
        x *= s;
        y *= s;
    }

    double length() const
    {
        return (sqrt(x * x + y * y));
    }

    void normalize()
    {
        const double len = length();
        assert(len != 0.0);

        x /= len;
        y /= len;
    }

    bool shares_2D_pos(const DXFSmoothPolylineVertex &v) const
    {
        return (x == v.x && y == v.y);
    }
};

class DXFSmoothPolyline
{
    // A DXF polyline that includes vertex bulge information.
    // Call Tessellate() to convert to an OGRGeometry.
    // We treat Z as constant over the entire string; this may
    // change in the future.

  private:
    std::vector<DXFSmoothPolylineVertex> m_vertices;
    mutable bool m_blinestringstarted;
    bool m_bClosed;
    int m_dim;
    bool m_bUseMaxGapWhenTessellatingArcs;

  public:
    DXFSmoothPolyline()
        : m_blinestringstarted(false), m_bClosed(false), m_dim(2),
          m_bUseMaxGapWhenTessellatingArcs(false)
    {
    }

    OGRGeometry *Tessellate() const;

    size_t size() const
    {
        return m_vertices.size();
    }

    void SetSize(int n)
    {
        m_vertices.reserve(n);
    }

    void AddPoint(double dfX, double dfY, double dfZ, double dfBulge)
    {
        m_vertices.push_back(DXFSmoothPolylineVertex(dfX, dfY, dfZ, dfBulge));
    }

    void Close();

    bool IsEmpty() const
    {
        return m_vertices.empty();
    }

    void setCoordinateDimension(int n)
    {
        m_dim = n;
    }

    void SetUseMaxGapWhenTessellatingArcs(bool bVal)
    {
        m_bUseMaxGapWhenTessellatingArcs = bVal;
    }

  private:
    void EmitArc(const DXFSmoothPolylineVertex &,
                 const DXFSmoothPolylineVertex &, double radius, double len,
                 double saggita, OGRLineString *, double dfZ = 0.0) const;

    void EmitLine(const DXFSmoothPolylineVertex &,
                  const DXFSmoothPolylineVertex &, OGRLineString *) const;
};

#endif /* OGRDXF_SMOOTH_POLYLINE_H_INCLUDED */
