/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2009  Sandro Santilli <strk@keybit.net>
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation. 
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: operation/buffer/BufferParameters.java r378 (JTS-1.12)
 *
 **********************************************************************/

#ifndef GEOS_OP_BUFFER_BUFFERPARAMETERS_H
#define GEOS_OP_BUFFER_BUFFERPARAMETERS_H

#include <geos/export.h>

//#include <vector>

//#include <geos/algorithm/LineIntersector.h> // for composition
//#include <geos/geom/Coordinate.h> // for composition
//#include <geos/geom/LineSegment.h> // for composition

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
#endif

// Forward declarations
namespace geos {
	namespace geom {
		class CoordinateSequence;
		class PrecisionModel;
	}
	namespace operation {
		namespace buffer {
			class OffsetCurveVertexList;
		}
	}
}

namespace geos {
namespace operation { // geos.operation
namespace buffer { // geos.operation.buffer

/** \brief
 * Contains the parameters which
 * describe how a buffer should be constructed.
 *
 */
class GEOS_DLL BufferParameters
{

public:

	/// End cap styles
        enum EndCapStyle {

                /// Specifies a round line buffer end cap style.
                CAP_ROUND=1,

                /// Specifies a flat line buffer end cap style.
                CAP_FLAT=2,

                /// Specifies a square line buffer end cap style.
                CAP_SQUARE=3
        };

	/// Join styles
        enum JoinStyle {

                /// Specifies a round join style.
                JOIN_ROUND=1,

                /// Specifies a mitre join style.
                JOIN_MITRE=2,

                /// Specifies a bevel join style.
                JOIN_BEVEL=3
        };

	/// \brief
	/// The default number of facets into which to divide a fillet
	/// of 90 degrees.
	//
	/// A value of 8 gives less than 2% max error in the buffer distance.
	/// For a max error of < 1%, use QS = 12.
	/// For a max error of < 0.1%, use QS = 18.
	///
	static const int DEFAULT_QUADRANT_SEGMENTS = 8;

	/// The default mitre limit
	//
	/// Allows fairly pointy mitres.
	///
	static const double DEFAULT_MITRE_LIMIT; // 5.0 (in .cpp file)

	/// Creates a default set of parameters
	BufferParameters();

	/// Creates a set of parameters with the given quadrantSegments value.
	//
	/// @param quadrantSegments the number of quadrant segments to use
	///
	BufferParameters(int quadrantSegments);

	/// \brief
	/// Creates a set of parameters with the
	/// given quadrantSegments and endCapStyle values.
	//
	/// @param quadrantSegments the number of quadrant segments to use
	/// @param endCapStyle the end cap style to use
	///
	BufferParameters(int quadrantSegments, EndCapStyle endCapStyle);

	/// \brief
	/// Creates a set of parameters with the
	/// given parameter values.
	//
	/// @param quadrantSegments the number of quadrant segments to use
	/// @param endCapStyle the end cap style to use
	/// @param joinStyle the join style to use
	/// @param mitreLimit the mitre limit to use
	///
	BufferParameters(int quadrantSegments, EndCapStyle endCapStyle,
	                 JoinStyle joinStyle, double mitreLimit);

	/// Gets the number of quadrant segments which will be used
	//
	/// @return the number of quadrant segments
	///
	int getQuadrantSegments() const { return quadrantSegments; }

	/// \brief
	/// Sets the number of line segments used to approximate
	/// an angle fillet.
	// 
	/// - If <tt>quadSegs</tt> >= 1, joins are round,
	///   and <tt>quadSegs</tt> indicates the number of
	///   segments to use to approximate a quarter-circle.
	/// - If <tt>quadSegs</tt> = 0, joins are bevelled (flat)
	/// - If <tt>quadSegs</tt> < 0, joins are mitred, and the value of qs
	///   indicates the mitre ration limit as
	///   <pre>
	///    mitreLimit = |<tt>quadSegs</tt>|
	///    </pre>
	/// 
	/// For round joins, <tt>quadSegs</tt> determines the maximum
	/// error in the approximation to the true buffer curve.
	///
	/// The default value of 8 gives less than 2% max error in the
	/// buffer distance.
	///
	/// For a max error of < 1%, use QS = 12.
	/// For a max error of < 0.1%, use QS = 18.
	/// The error is always less than the buffer distance
	/// (in other words, the computed buffer curve is always inside
	///  the true curve).
	///
	/// @param quadrantSegments the number of segments in a
	///                         fillet for a quadrant
	////
	void setQuadrantSegments(int quadSegs);

	/// \brief
	/// Computes the maximum distance error due to a given level
	/// of approximation to a true arc.
	//
	/// @param quadSegs the number of segments used to approximate
	///                 a quarter-circle
	/// @return the error of approximation
	///
	static double bufferDistanceError(int quadSegs);

	/// Gets the end cap style.
	//
	/// @return the end cap style
	///
	EndCapStyle getEndCapStyle() const { return endCapStyle; }

	/// Specifies the end cap style of the generated buffer.
	//
	/// The styles supported are CAP_ROUND, CAP_BUTT,
	/// and CAP_SQUARE.
	///
	/// The default is CAP_ROUND.
	///
	/// @param style the end cap style to specify
	///
	void setEndCapStyle(EndCapStyle style)
	{
		endCapStyle = style;
	}

	/// Gets the join style.
	//
	/// @return the join style
	///
	JoinStyle getJoinStyle() const { return joinStyle; }

	/// \brief
	/// Sets the join style for outside (reflex) corners between
	/// line segments.
	//
	/// Allowable values are JOIN_ROUND (which is the default),
	/// JOIN_MITRE and JOIN_BEVEL.
	//
	/// @param style the code for the join style
	///
	void setJoinStyle(JoinStyle style)
	{
		joinStyle = style;
	}

	/// Gets the mitre ratio limit.
	//
	/// @return the limit value
	///
	double getMitreLimit() const { return mitreLimit; }
 
	/// Sets the limit on the mitre ratio used for very sharp corners.
	//
	/// The mitre ratio is the ratio of the distance from the corner
	/// to the end of the mitred offset corner.
	/// When two line segments meet at a sharp angle,
	/// a miter join will extend far beyond the original geometry.
	/// (and in the extreme case will be infinitely far.)
	/// To prevent unreasonable geometry, the mitre limit
	/// allows controlling the maximum length of the join corner.
	/// Corners with a ratio which exceed the limit will be beveled.
	///
	/// @param limit the mitre ratio limit
	///
	void setMitreLimit(double limit)
	{
		mitreLimit = limit;
	}

	/**
	 * Sets whether the computed buffer should be single-sided.
	 * A single-sided buffer is constructed on only one side of each input line.
	 * 
	 * The side used is determined by the sign of the buffer distance:
	 * - a positive distance indicates the left-hand side
	 * - a negative distance indicates the right-hand side
	 * 
	 * The single-sided buffer of point geometries is
	 * the same as the regular buffer.
	 *
	 * The End Cap Style for single-sided buffers is
	 * always ignored,
	 * and forced to the equivalent of <tt>CAP_FLAT</tt>.
	 *
	 * @param isSingleSided true if a single-sided buffer should be constructed
	 */
	void setSingleSided(bool isSingleSided)
	{
	  _isSingleSided = isSingleSided;
	}

	/**
	 * Tests whether the buffer is to be generated on a single side only.
	 *
	 * @return true if the generated buffer is to be single-sided
	 */
	bool isSingleSided() const {
	  return _isSingleSided;
	}


private:

	/// Defaults to DEFAULT_QUADRANT_SEGMENTS;
	int quadrantSegments;

	/// Defaults to CAP_ROUND;
	EndCapStyle endCapStyle;

	/// Defaults to JOIN_ROUND;
	JoinStyle joinStyle;

	/// Defaults to DEFAULT_MITRE_LIMIT;
	double mitreLimit;

	bool _isSingleSided;
};

} // namespace geos::operation::buffer
} // namespace geos::operation
} // namespace geos

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#endif // ndef GEOS_OP_BUFFER_BUFFERPARAMETERS_H

