// Geometric Tools, Inc.
// http://www.geometrictools.com
// Copyright (c) 1998-2005.  All Rights Reserved
//
// The Wild Magic Library (WM3) source code is supplied under the terms of
// the license agreement
//     http://www.geometrictools.com/License/WildMagic3License.pdf
// and may not be copied or disclosed except in accordance with the terms
// of that agreement.

#ifndef WM3CONVEXPOLYHEDRON3_H
#define WM3CONVEXPOLYHEDRON3_H

#include "Wm3Polyhedron3.h"
#include "Wm3Plane3.h"
#include <set>

namespace Wm3
{

template <class Real>
class ConvexPolyhedron3 : public Polyhedron3<Real>
{
public:
    // Construction and destruction.  The caller is responsible for ensuring
    // that the mesh represents a convex polyhedron.  The triangular faces
    // must be ordered counterclockwise when viewed from outside the mesh.
    // To assign ConvexPolyhedron3 the ownership of the input arrays, set
    // bOwner to 'true'; otherwise, set it to 'false', in which case the
    // caller is responsible for deleting the arrays if they were dynamically
    // allocated.
    //
    // The class stores the planes associated with the faces, and the plane
    // normals are inner pointing.  The planes may be supplied to the
    // constructor, in which case the ownership flag applies.  If they are not
    // passed (akPlane is null), the class automatically generates them and
    // owns this array, even if the other arrays are not owned.
    ConvexPolyhedron3 (int iVQuantity, Vector3<Real>* akVertex,
        int iTQuantity, int* aiIndex, Plane3<Real>* akPlane, bool bOwner);

    // Copy constructor.  If the input polyhedron owns its data, then a copy
    // is made for 'this' object, in which case 'this' owns its data.  If the
    // input polyhedron does not own its data, 'this' shares that same data
    // so does not own it.
    ConvexPolyhedron3 (const ConvexPolyhedron3& rkPoly);

    virtual ~ConvexPolyhedron3 ();

    // Assignment.  If the input polyhedron owns its data, then a copy is
    // made for 'this' object, in which case 'this' owns its data.  If the
    // input polyhedron does not own its data, 'this' shares that same data
    // so does not own it.
    ConvexPolyhedron3& operator= (const ConvexPolyhedron3& rkPoly);

    // read-only member access
    const Plane3<Real>* GetPlanes () const;
    const Plane3<Real>& GetPlane (int i) const;

    // Allow vertex modification.  The caller must guarantee that the mesh
    // will remain convex.  After modifying as many vertices as you like,
    // call UpdatePlanes().  If the modifications are all done via SetVertex,
    // then the planes are updated only for those triangles affected by the
    // modifications.  If any modifications are done by accessing the vertex
    // array via GetVertices, this class has no knowledge of the changes, in
    // which case UpdatePlanes() will recompute all the planes.
    virtual void SetVertex (int i, const Vector3<Real>& rkV);
    void UpdatePlanes ();

    // Test for convexity.  This function will iterate over the faces of the
    // polyhedron and verify for each face that the polyhedron vertices are
    // all on the nonnegative side of the facet plane.  A signed distance test
    // is used, so a vertex is on the wrong side of a plane (for convexity)
    // when its signed distance satisfies d < 0.  Numerical round-off errors
    // can generate incorrect convexity tests, so a small negative threshold
    // t may be passed to this function, in which case the distance test
    // becomes d < t < 0.
    bool IsConvex (Real fThreshold = (Real)0.0) const;

    // Point-in-polyhedron test.  The threshold serves the same purpose as
    // the one in IsConvex.
    bool ContainsPoint (const Vector3<Real>& rkP, Real fThreshold = (Real)0.0)
        const;

protected:
    using Polyhedron3<Real>::m_iVQuantity;
    using Polyhedron3<Real>::m_akVertex;
    using Polyhedron3<Real>::m_iTQuantity;
    using Polyhedron3<Real>::m_aiIndex;

    Plane3<Real>* m_akPlane;
    bool m_bPlaneOwner;

    // Support for efficient updating of facet planes.  The set stores the
    // indices for those triangles affected by modifying vertices.
    void UpdatePlane (int i, const Vector3<Real>& rkAverage);
    std::set<int> m_kTModified;
};

#include "Wm3ConvexPolyhedron3.inl"

typedef ConvexPolyhedron3<float> ConvexPolyhedron3f;
typedef ConvexPolyhedron3<double> ConvexPolyhedron3d;

}

#endif
