/* 
 * Routines to create a line of best fit when given a set of coord pairs.
 */

#include "enforce.h"
#include <grass/glocale.h>


/*
 * pg_init - initialize PointGrp variables
 */
void pg_init(PointGrp *pg)
{
    pg->sum_x = pg->sum_y = pg->sum_xy = pg->sum_x_sq = 0.0;
    pg->npts = 0;
}


/*
 * pg_y_from_x - determine y value for a given x value in a PointGrp
 */
double pg_y_from_x(PointGrp *pg, const double x)
{ 
    return ((pg->slope * x) + pg->yinter); 
}


/*
 * pg_addpt - Add a point to a PointGrp
 */
void pg_addpt(PointGrp *pg, Point2 pt)
{
    if (pg->npts < MAX_PTS - 1)
    {
        double x = pt[0];
        double y = pt[1];

        /* add point to group */
        pg->pnts[pg->npts][0] = x;
        pg->pnts[pg->npts][1] = y;
        pg->sum_x += x;
        pg->sum_y += y;
        pg->sum_xy += (x * y); 
        pg->sum_x_sq += SQR(x);
        ++pg->npts;
    }

    if (pg->npts > 1)
    {
        double denom;

        /* solve for x and y using Cramer's Rule */

        /* check for divide by zero */
        if (0 == (denom = DET2_2(pg->sum_x_sq, pg->sum_x, pg->sum_x, pg->npts)))
        {
            G_warning(_("trying to divide by zero...no unique solution for "
                        "system...skipping..."));
            pg->slope = pg->yinter = 0.0;
        }
        else
        {
            pg->slope  = DET2_2(pg->sum_xy, pg->sum_x, pg->sum_y, pg->npts) / 
                         denom;
            pg->yinter = DET2_2(pg->sum_x_sq, pg->sum_xy, pg->sum_x, pg->sum_y) /
                         denom;
        }
    }
}


/*
 * pg_getpoints - returns the Point2 structure from a PointGrp
 */
Point2 *pg_getpoints(PointGrp *pg)
{
    return pg->pnts;
}


/*
 * pg_getpoints_reversed - reverse points in PointGrp and returns Point2
 */
Point2 *pg_getpoints_reversed(PointGrp *pg)
{
    int i;
    int iter = pg->npts / 2;
    double x, y;

    for (i = 0; i < iter; i++) {
        /* swap points */
        x = pg->pnts[i][0];
        y = pg->pnts[i][1];
        pg->pnts[i][0] = pg->pnts[pg->npts-i-1][0];
        pg->pnts[i][1] = pg->pnts[pg->npts-i-1][1];
        pg->pnts[pg->npts-i-1][0] = x;
        pg->pnts[pg->npts-i-1][1] = y;
    }

    return pg->pnts;
}
