#ifndef POLYTOPED2LINKED_H
#define POLYTOPED2LINKED_H

#include <cassert>
#include <vector>
using namespace std;


#include <typedefs.h>

/*!
\brief Linked polygons. 

NOTE: Suspend development. The primary problem is with
 memory reallocation, for example adding a point. 
 However once this type of structure has stabalized
 the array is ideal as it reduces the memory requirements
 and provides fast access, so this class may be implemented
 for this purpose - as an optimization.

The points have an anti clockwise winding.
 ni[k] points to the neighboring polygon on the
 edge from pi[k] to pi[k+1].

Traveling anti clockwise around the points forms a polygon.
 ni[k] is link at pi[k] to another polygon. The side of the
 link is pi[k] to pi[k+1] and is right of the line.

For infinite regions a neighbor having a value of 0.
 Or it could also mean that there is no link. So
 a value of 0 in ni[] is dependent on the context/algorithm
 using this data structure.
*/
class polytopeD2linked
{
public:

  /** Indexes to the points. */
  vector<uint> pi;
  /** Indexes to the neighbors. */
  vector<uint> ni;

  /** Use global points as references to get the opposite 
      neighbor. */
  uintc nifrom( uintc gpt ) const
    { return ni[piInverse(gpt)]; }

  /** Construct a null polytope. */
  polytopeD2linked() {}

  /** A line. */
  polytopeD2linked(uintc p0, uintc p1, uintc n0, uintc n1);
  /** A triangle. */
  polytopeD2linked
  (
    uintc p0, uintc p1, uintc p2,
    uintc n0, uintc n1, uintc n2
  );
  /** A quadrilateral. */
  polytopeD2linked
  (
    uintc p0, uintc p1, uintc p2, uintc p3,
    uintc n0, uintc n1, uintc n2, uintc n3
  );
  /** A 5 point polygon. */
  polytopeD2linked
  (
    uintc p0, uintc p1, uintc p2, uintc p3, uintc p4,
    uintc n0, uintc n1, uintc n2, uintc n3, uintc n4
  );
  /** A 6 point polygon. */
  polytopeD2linked
  (
    uintc p0, uintc p1, uintc p2, uintc p3, uintc p4, uintc p5,
    uintc n0, uintc n1, uintc n2, uintc n3, uintc n4, uintc n5
  );
  /** A 7 point polygon. */
  polytopeD2linked
  (
    uintc p0, uintc p1, uintc p2, uintc p3, uintc p4, uintc p5, uintc p6,
    uintc n0, uintc n1, uintc n2, uintc n3, uintc n4, uintc n5, uintc n6
  );
  /** A 8 point polygon. */
  polytopeD2linked
  (
    uintc p0, uintc p1, uintc p2, uintc p3, uintc p4, uintc p5, uintc p6, uintc p7,
    uintc n0, uintc n1, uintc n2, uintc n3, uintc n4, uintc n5, uintc n6, uintc n7
  );
  /** Add to end of polytope point and neighbor list. */
  polytopeD2linked & add(uintc p, uintc n)
    { pi.push_back(p); ni.push_back(n); return *this; }

  /** Get the local point index. */
  uintc piInverse( uintc gpt ) const
  {
    assert(gpt!=0);
    uintc sz = pi.size();
    for ( uint i=0; i<sz; ++i)
      if (pi[i]==gpt)
        return i;

    assert(false);
    return sz+1;
  }

  /** Is this polytope not constructed? */
  boolc isnull() const
    { return pi.empty(); }

  /** Does the polytope have a link to this neighbor? */
  boolc niInverseHas( uintc neib ) const;

  /** Write the object out. */
  operator string() const;

  /** Add a new point to the polytope, the insert position
      indexed with an existing polygon point. */
  void addpoint( uintc ptindex, uintc ptglobal );
};




#endif



