/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
* Copyright 2016 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
*/

#ifndef BOUNDARY_UTIL
#define BOUNDARY_UTIL 1

#include <osg/Node>

class BoundaryUtil
{
public:
    BoundaryUtil();

    /** Sets the tolerance when combining close verts. Default = 0.01 */
    static void setTolerance(double meters);
    static double getTolerance() { return _tolerance; }

    /**
     * Use the vertices of the given node to calculate a boundary via the
     * findHull() method.
     */
    static osg::Vec3dArray* getBoundary(osg::Node* modelNode, bool geocentric=true, bool convexHull=false);

    /**
     * Finds the convex hull for the given points using the Andrew's monotone
     * chain algorithm. Returns an ordered set of points defining the hull
     */
    static osg::Vec3dArray* findHull(osg::Vec3dArray& points);

    static osg::Vec3dArray* findMeshBoundary(osg::Node* modelNode, bool geocentric=true);

    static bool simpleBoundaryTest(const osg::Vec3dArray& boundary);

protected:
    /* Returns an array containing the points sorted first by x and then by y */
    static osg::Vec3dArray* hullPresortPoints(osg::Vec3dArray& points);

    /* Tests if a point is Left|On|Right of an infinite line
    *   Returns: >0 for P2 left of the line through P0 and P1
    *            0 for P2 on the line
    *            <0 for P2 right of the line
    *
    * Implementation based on method from softSurfer (www.softsurfer.com)
    */
    static inline float isLeft(osg::Vec3d P0, osg::Vec3d P1, osg::Vec3d P2)
    {
        return (P1.x() - P0.x())*(P2.y() - P0.y()) - (P2.x() - P0.x())*(P1.y() - P0.y());
    }

    static double _tolerance;
};

#endif // BOUNDARY_UTIL
