/*
    This software may only be used by you under license from AT&T Corp.
    ("AT&T").  A copy of AT&T's Source Code Agreement is available at
    AT&T's Internet website having the URL:
    <http://www.research.att.com/sw/tools/graphviz/license/source.html>
    If you received this software without first entering into a license
    with AT&T, you have an infringing copy of this software and cannot use
    it without violating AT&T's intellectual property rights.
*/
#pragma prototyped
#include <stdio.h>
#include "neato.h"
#include "mem.h"
#include "info.h"


Info_t*    nodeInfo;          /* Array of node info */
static Freelist pfl;

void
infoinit ()
{
    freeinit(&pfl, sizeof (PtItem));
}

/* compare:
 * returns -1 if p < q
 *          0 if p = q
 *          1 if p > q
 * if q if NULL, returns -1
 * Ordering is by angle from -pi/2 to 3pi/4.
 * For equal angles (which should not happen in our context)
 * ordering is by closeness to origin.
 */
static int
compare (Point* o, PtItem* p, PtItem* q)
{
    double x0;
    double y0;
    double x1;
    double y1;
    double a, b;

    if (q == NULL) return -1;
    if ((p->p.x == q->p.x) && (p->p.y == q->p.y)) return 0;

    x0 = ((double)(p->p.x)) - ((double)(o->x));
    y0 = ((double)(p->p.y)) - ((double)(o->y));
    x1 = ((double)(q->p.x)) - ((double)(o->x));
    y1 = ((double)(q->p.y)) - ((double)(o->y));
    if (x0 >= 0.0) {
      if (x1 < 0.0) return -1;
      else if (x0 > 0.0) {
        if (x1 > 0.0) {
          a = y1/x1;
          b = y0/x0;
          if (b < a) return -1;
          else if (b > a) return 1;
          else if (x0 < x1) return -1;
          else return 1;
        }
        else {  /* x1 == 0.0 */
          if (y1 > 0.0) return -1;
          else return 1;
        }
      }
      else {        /* x0 == 0.0 */
        if (x1 > 0.0) {
          if (y0 <= 0.0) return -1;
          else return 1;
        }
        else {    /* x1 == 0.0 */
          if (y0 < y1) {
            if (y1 <= 0.0) return 1;
            else return -1;
          }
          else {
            if (y0 <= 0.0) return -1;
            else return 1;
          }
        }
      }
    }
    else {
      if (x1 >= 0.0) return 1;
      else {
          a = y1/x1;
          b = y0/x0;
          if (b < a) return -1;
          else if (b > a) return 1;
          else if (x0 > x1) return -1;
          else return 1;
      }
    }
}

#if 0 /* not used */
static void
printV (PtItem *vp)
{
    if (vp == NULL) {
       fprintf (stderr, "<empty>\n");
       return;
    }

    while (vp != NULL) {
       fprintf (stderr, "(%.16f,%.16f)\n", vp->p.x, vp->p.y);
       vp = vp->next;
    }
}

static void
error (Info_t* ip, Site* s, double x, double y)
{
    fprintf (stderr, "Unsorted vertex list for site %d (%.16f,%.16f), pt (%f,%f)\n",
        s->sitenbr, s->coord.x, s->coord.y, x, y);
    printV (ip->verts);
}
#endif

#if 0 /* not used */
static int
sorted (Point* origin, PtItem* vp)
{
    PtItem*  next;

    if (vp == NULL) return 1;
    next = vp->next;

    while(next != NULL) {
      if (compare(origin,vp,next) <= 0) {
         vp = next;
         next = next->next;
      }
      else {
          fprintf (stderr, "(%.16f,%.16f) > (%.16f,%.16f)\n",
            vp->p.x, vp->p.y, next->p.x, next->p.y);
          return 0;
      }
    }

    return 1;
    
}
#endif

void 
addVertex (Site* s, double x, double y)
{
    Info_t*   ip;
    PtItem*   p;
    PtItem*   curr;
    PtItem*   prev;
    Point*    origin = &(s->coord);
    PtItem    tmp;
    int       cmp;

    ip = nodeInfo + (s->sitenbr);
    curr = ip->verts;

    tmp.p.x = x;
    tmp.p.y = y;

    cmp = compare(origin, &tmp, curr);
    if (cmp == 0) return;
    else if (cmp < 0) {
        p = (PtItem *) getfree(&pfl);
        p->p.x = x;
        p->p.y = y;
        p->next = curr;
        ip->verts = p;
        return;
    }

    prev = curr;
    curr = curr->next;
    while ((cmp = compare(origin, &tmp, curr)) > 0) {
        prev = curr;
        curr = curr->next;
    }
    if (cmp == 0) return;
    p = (PtItem *) getfree(&pfl);
    p->p.x = x;
    p->p.y = y;
    prev->next = p;
    p->next = curr;

    /* This test should be unnecessary */
      /* if (!sorted(origin,ip->verts))  */
        /* error (ip,s,x,y); */

}
