/*
 $Id: feplot1.cc,v 1.4 1996/11/20 10:00:04 roitzsch Exp $
 (C)opyright 1996 by Konrad-Zuse-Center, Berlin
 All rights reserved.
 Part of the Kaskade distribution
*/

#include "feplot1.h"
#include "triang1.h"

#include "utils.h"
#include "numerics.h"

// static const Real EPS = 1e-6;

//-------------------------------------------------------------------------


FEPlotMESH1:: FEPlotMESH1(MESH* t, int plotType, char* caption, float size)
{
    backCol 	 = WHITE;
    dirichletCol = RED; 
    neumannCol 	 = BLUE; 
    cauchyCol 	 = GREEN;
    triFineCol	 = BLACK;
    triCoarseCol = MAGENTA;
    levelCol     = RED;

    mesh = t->castToMESH1();

    const char *dummyCaption = "FePlot",  *cp;

    if (caption==0)  cp = dummyCaption;
    else	     cp = caption;

    plotSize = size;
    plot = new Plot(plotType, size, cp);

    plot->set(SCALFIT,0);
    setMinMaxX();
    setMinMaxY();
}
//-------------------------------------------------------------------------

void FEPlotMESH1:: updateMesh(MESH* t) { mesh = t->castToMESH1(); }

//-------------------------------------------------------------------------

void FEPlotMESH1:: plotSolution(Vector<Real>& u)
{
    int   node;
    EDG1* ed;
    PT1*  pt;

    setMinMaxY(u);
    plotElements();

    plot->set(PENCOL, levelCol);
    plot->set(PENSIZE,SMALL);

    DListIter<EDG1>  iter(mesh->edges());
    while ((ed = iter.all())) plotSolElement(ed,u);

    plot->set(FONTSIZE,SMALL);

    char line[100];
    Real uMin = machMax(Real(0)), uMax = -machMax(Real(0));

    DListIter<PT1> ptIter(mesh->points());
    while ((pt = ptIter.all()))
    {
	node = pt->node;
	if (u[node] < uMin) uMin = u[node];
	if (u[node] > uMax) uMax = u[node];
    }

    Real xdiff = (xMax-xMin)/10;
    Real ydiff = (yMax-yMin)/10.;

    sprintf(line,"Min: %1.4g   Max: %1.4g", uMin, uMax);
    plot->text(xMin+xdiff, yMax-0.5*ydiff, line);

    flush();
}
//-------------------------------------------------------------------------

void FEPlotMESH1:: plotSolElement(EDG1 *e, Vector<Real>& u)
{
    Real x[2], y[2];

    x[0] = e->p1->x; 
    x[1] = e->p2->x;

    y[0] = u[e->p1->getNode()];
    y[1] = u[e->p2->getNode()];

    plot->line(x, y, 2);
}
//-------------------------------------------------------------------------


void FEPlotMESH1:: plotPointNodes()
{
    char line[10];

    plotElements(); 

    Real xdiff = (xMax-xMin)/50.;
    Real ydiff = (yMax-yMin)/15.;

    if (plotSize > 0.5) plot->set(FONTSIZE, MEDIUM);
    else     		plot->set(FONTSIZE, SMALL);
    plot->set(FONTCOL, BLACK);

    PT1* pt;
    DListIter<PT1>  iter(mesh->points());

    while ((pt = iter.all())) 
    {
	sprintf(line, "%1d(%1d)", pt->node, pt->depth);
	plot->text ((pt->x)-xdiff, y0+ydiff, line);
	ydiff *= -1;
    }
    flush();
}
//-------------------------------------------------------------------------

void FEPlotMESH1:: plotEdgeNodes()
{
    char line[10];

    plotElements(); 

    Real xdiff = (xMax-xMin)/50.;
    Real ydiff = (yMax-yMin)/15.;

    if (plotSize > 0.5) plot->set(FONTSIZE, MEDIUM);
    else     		plot->set(FONTSIZE, SMALL);
    plot->set(FONTCOL, BLACK);

    EDG1 *ed;
    DListIter<EDG1> iter(mesh->edges());

    while ((ed = iter.all()))
    {
	sprintf(line, "%1d(%1d)", ed->node, ed->depth);
	plot->text(0.5*(ed->p1->x + ed->p2->x) - xdiff, y0+ydiff, line);
    }
    plot->flush();
}
//-------------------------------------------------------------------------


void FEPlotMESH1:: plotElements()
{
    EDG1* ed;
    plot->set(PENSIZE, SMALL);
    plot->set(PENCOL,  triFineCol);

    DListIter<EDG1> iter(mesh->edges());
    while ((ed = iter.all())) plotEdge(ed); 
    plot->flush();
}
//-------------------------------------------------------------------------

void FEPlotMESH1:: plotEdge(EDG1* ed)
{
    Real x[2], y[2], dy;

    if (ed->firstSon != nil) return; 

    x[0] = ed->p1->x; 
    x[1] = ed->p2->x;

    y[0] = y[1] = y0;		  	// plot at zero-level (y0)
    plot->line(x,y,2);

    dy = 0.25*0.1*(yMax-yMin);	
    y[0] = y0 + dy;
    y[1] = y0 - dy;

    x[0] = x[1] = ed->p1->x;
    plot->line(x,y,2);
    x[0] = x[1] = ed->p2->x;
    plot->line(x,y,2);
}
//-------------------------------------------------------------------------

void FEPlotMESH1:: setMinMaxX()
{
    int depth = 0;
    Real dx;
    PT1* p;
    xMin= machMax(Real(0)); xMax= -machMax(Real(0));

    DListIter<PT1> iter(mesh->points(),depth);

    while ((p = iter.all())) 
    {
	if (p->x < xMin) xMin = p->x;
	if (p->x > xMax) xMax = p->x;
    }
 
    dx = (xMax-xMin)/10.0;
    xMin -= dx; 
    xMax += dx;
    plot->set(MINX, xMin);
    plot->set(MAXX, xMax);
}
//-------------------------------------------------------------------------

void FEPlotMESH1:: setMinMaxY()		// kind of a dummy
{
    yMin = xMin; 
    yMax = xMax;

    Real dy = (yMax-yMin)/10.0;
    yMin -= dy; 
    yMax += dy;

    plot->set(MINY, yMin);
    plot->set(MAXY, yMax);

    y0 = yMin + dy;
}
//-------------------------------------------------------------------------


void FEPlotMESH1:: setMinMaxY(Vector<Real>& u)		// for solution plots
{
    int node;
    Real dy;
    PT1* pt;

    yMin = machMax(Real(0)), yMax = -machMax(Real(0));

    DListIter<PT1> ptIter(mesh->points());
    while ((pt = ptIter.all()))
    {
	node = pt->node;
	if (u[node] < yMin) yMin = u[node];
	if (u[node] > yMax) yMax = u[node];
    }
 
    if (equal(yMin,yMax)) 		// might be the case for level 0
    {
	yMin -= 1.0; 
	yMax += 1.0;
    }	

    dy = (yMax-yMin)/10.0;
    yMin -= dy; 
    yMax += dy;
    
    plot->set(MINY, yMin);
    plot->set(MAXY, yMax);
    
    y0 = yMin + dy;
}
