// plot2d.js

//  --------------------------------------------------------------------------->
/* <p>Title: Plot-Unit</p>
 * <p>Description: Plot-Routines for compatibility with older sources</p>
 * <p>Copyright: Copyright (c) 2010</p>
 * <p>Company: SiG Software Integration GmbH</p>
 * @author Dr. Horst Walther
 * @version date 01.04.2010
 * @version 1.35 */
//  --------------------------------------------------------------------------->

//  --------------------------------------------------------------------------->
function plot2d(id, width, height, fill, opacity) {

  var wordy = false;
  var screenResCorr = 0.5208333;
  var incWL = 5;
  var minVisWL = 380;
  var BLANK = ' ';
  var colour = 1,
    palette = 1,
    backGround = 0,
    lineType, 
    xPixelFactor = 52, // pixel per cm
    yPixelFactor = 52, // pixel per cm
    xPixelOld = 0,
    yPixelOld = 0,
    xPixelMax = screen.width,
    yPixelMax = screen.height,
    xPixelMaxInit = xPixelMax,
    yPixelMaxInit = yPixelMax,
    ScreenFactor;
  var
    xZero = 0,
    yZero = 0,
    factor = 1.0,
    xMin = 0.0,
    yMin = 0.0,
    xMax = 10.0,
    yMax = 10.0,
    xOld = 0.0,
    yOld = 0.0,
    lineWidth = 1.0;

  var tmpColor;
  var offScreenImage; // = createImage (10, 10);

  this.id = "plot2d";
  this.status = 'initialised';
  this.SIG_BLUE = Color(102, 153, 255);
  this.SIG_OCKER = Color(254, 187, 96);
  this.SIG_GREY = Color(239, 239, 239);
  this.NAVY = Color(0, 0, 128);
  this.uniqueID = new Array;

  //  ----------------------------------------------------------------------------
  this.paint = function() {
    return g.paint();
  };

 //  --------------------------------------------------------------------------->
  this.getUniqueID = function (i) {
    if (this.uniqueID[i] == undefined) this.uniqueID[i] = 0;
    return i+this.uniqueID[i]++;
  }
  //  --------------------------------------------------------------------------->
  this.getGraphics = function () {
    if (!g) alert ('###  plot2d.getGraphics: g is undefined!');
    return g;
  }

//  --------------------------------------------------------------------------->
this.Position2d = function(x, y) {
  this.x = x == undefined ? 0.0 : x;
  this.y = y == undefined ? 0.0 : y;

  this.transform = function(){
    return new p2d.Position2d (p2d.transformX(this.x), p2d.transformY(this.y));
  }

  this.getX = function () {
    return this.x;
  }

  this.getY = function () {
    return this.y;
  }

  this.setX = function (x) {
    this.x = x;
    return this;
  }

  this.setY = function (y) {
    this.y = y;
    return this;
  }

  this.shift = function (isXaxis, shift) {
    this.x = isXaxis ? this.x : this.x + shift;
    this.y = isXaxis ? this.y + shift : this.y;
    return this;
  }

  this.unShift = function (isXaxis, shift) {
//    alert ('before: '+this.toString());
    this.x = isXaxis ? this.x : this.x - shift;
    this.y = isXaxis ? this.y - shift : this.y;
//    alert ('after: '+this.toString());
    return this;
  }

  this.toString = function () {
    return this.x + ", " + this.y
  }
  return this;
}

function HexToR(h) {
  return parseInt((cutHex(h)).substring(0, 2), 16)
}

function HexToG(h) {
  return parseInt((cutHex(h)).substring(2, 4), 16)
}

function HexToB(h) {
  return parseInt((cutHex(h)).substring(4, 6), 16)
}

function cutHex(h) {
  return (h.charAt(0) == "#") ? h.substring(1, 7) : h
}

function HexToRGB(h) {
  return new Array(HexToR(h), HexToG(h), HexToB(h))
};

  //  --------------------------------------------------------------------------->
  this.setBackGroundColor = function (color) {
//    alert (this.id+'.setBackGroundColor ('+color+')');
    return g.setBackGroundColor(color);
  }

  //  ----------------------------------------------------------------------------
  this.removeNode = function (node) {
    if (!node) return false;
    if (!node.parentNode) return false;
    node.parentNode.removeChild(node);
    return true;
  }

  //  --------------------------------------------------------------------------->
  this.reset = function (iOff, x, y) {
    var wordy = false;
    if (wordy) alert("iOff=" + iOff + ", width=" + x + ", height=" + y);
    //   g = iOff.getGraphics ();
    //   this.offScreenImage = iOff;
    var maxD = new Position2d(parseInt(screen.availHeight), parseInt(screen.availHeight)) // Toolkit.getDefaultToolkit ().getScreenSize ();
    if (x <= 0) x = maxD.width;  // -->
    if (y <= 0) y = maxD.height; // -->
    ScreenFactor = 100; // (Toolkit.getDefaultToolkit ().getScreenResolution ()*screenResCorr); // weil in dpi
    if (wordy) alert("plot2d.reset (" + x + ", " + y + "), Alt = " + xPixelOld + ", " + yPixelOld + "), screenFactor =" + ScreenFactor);
    xPixelFactor = ScreenFactor;
    yPixelFactor = ScreenFactor;
    setSize(new Position2d(x, y));
    xZero = 0;
    yZero = 0;
    xMin = 0.0;
    yMin = 0.0;
    xOld = 0.0;
    yOld = 0.0;
    lineWidth = 1.0;
    if (wordy) alert(".reset (" + x + ", " + y + "), getFactor ()=" + getFactor() + ", x=" + x + ", xPixelMax=" + xPixelMax + ", y=" + y + ", yPixelMax=" + yPixelMax);
    //  getOffScreenGraphics ().clearRect (0, 0, x, y);
  }

  //  --------------------------------------------------------------------------->
  this.getSize = function () {
    alert('plot2d.getSize (' + xMax + ', ' + yMax + ')');
    return new Position2d(xMax, yMax);
  }

  //  --------------------------------------------------------------------------->
  this.resize = function (p, factorX, factorY) {
    factorY = factorY ? factorY : factorX;
    if (!factorX) {
      var newSize = getMaxSize ();
      factorX = (newSize.width-this.getUnavail().width)  / (p.maxSize.width-this.getUnavail().width);
      factorY = (newSize.height-this.getUnavail().height) / (p.maxSize.height-this.getUnavail().height); 
//      alert ('maxSize='+p.maxSize.width+', '+p.maxSize.height);
//      alert ('newSize='+newSize.width   +', '+newSize.height);
//      alert ('factor.x='+ factorX);
//      alert ('factor.y='+ factorY);
    }
    p.maxSize = getMaxSize ();
    p.scale (p.getTotalId(), factorX, factorY);
    return p.getGraphics().resizeCanvas (factorX, factorY);
  };

  //  --------------------------------------------------------------------------->
  this.getTotalId = function () {
    return g.getTotalId ();
  };

  //  --------------------------------------------------------------------------->
  this.getUnavail = function () {
//    alert ('getUnavail: '+this.unavail.width+', '+this.unavail.height);
    return g.getUnavail();
  };

  //  --------------------------------------------------------------------------->
  this.setUnavail = function (width, height) {
    g.setUnavail (width, height);
//    alert ('setUnavail: '+this.unavail.width+', '+this.unavail.height);
    return this;
  };

  //  --------------------------------------------------------------------------->
  this.getPixelSize = function () {
    return new Position2d(xPixelMax, yPixelMax);
  }

  //  --------------------------------------------------------------------------->
  this.setSize = function (d) {
    xPixelMax = d.width;
    yPixelMax = d.height;
    xPixelOld = 0;
    yPixelOld = yPixelMax;
    xPixelMaxInit = xPixelMax;
    yPixelMaxInit = yPixelMax;
    xMax = xPixelMax / xPixelFactor;
    yMax = yPixelMax / yPixelFactor;
  }

  //  --------------------------------------------------------------------------->
  this.SetMinMaxX = function (x) {
    xMax = Math.max(xMax, x);
    xMin = Math.min(xMin, x);
    return this;
  }

  //  --------------------------------------------------------------------------->
  this.SetMinMaxY = function (y) {
    if (y > yMax) yMax = y;
    if (y < yMin) yMin = y;
    return this;
  }

  //  --------------------------------------------------------------------------->
  this.setFactor = function (f) {
    factor = f;
    this.setSize(new Position2d(xPixelMax * f, yPixelMax * f));
    g.setBackGroundSize(factor);
  }

  //  --------------------------------------------------------------------------->
  this.getFactor = function () {
    return factor;
  }

  //  --------------------------------------------------------------------------->
  this.GetPositionY = function () {
    return (yOld);
  }

  //  --------------------------------------------------------------------------->
  this.GetPositionX = function () {
    return (xOld);
  }

  //  --------------------------------------------------------------------------->
  this.GetPixelX = function () {
    return (xPixelOld);
  }
  //  --------------------------------------------------------------------------->
  this.GetPixelY = function () {
    return (yPixelOld);
  }

  //  --------------------------------------------------------------------------->
  this.getXpixelMax = function () {
    return xPixelMaxInit;
  }

  //  --------------------------------------------------------------------------->
  this.getYpixelMax = function () {
    return yPixelMaxInit;
  }

  //  --------------------------------------------------------------------------->
  this.toPixelX = function (v) {
    return (v * xPixelFactor);
  }

  //  --------------------------------------------------------------------------->
  this.toPixelY = function (v) {
    return (v * yPixelFactor);
  }

  //  --------------------------------------------------------------------------->
  this.toPixel = function (v) {
    return (v * xPixelFactor * yPixelFactor * 0.5);
  }

  //  --------------------------------------------------------------------------->
  this.toScreenX = function (v) {
    return toScreen(v);
  }

  //  --------------------------------------------------------------------------->
  this.toScreenY = function (v) {
    return toScreen(v);
  }

  //  --------------------------------------------------------------------------->
  this.toScreen = function (v) {
    return (v * ScreenFactor);
  }

  //  --------------------------------------------------------------------------->
  this.toPixelX = function (x) {
    if (x == null) return null;
    xPixelOld = (x * xPixelFactor);
    return Math.round(xPixelOld);
  }

  //  --------------------------------------------------------------------------->
  this.toPixelY = function (y) {
    if (y == null) return null;
    yPixelOld = yPixelMax - y * yPixelFactor;
    return Math.round(yPixelOld);
  }

  //  --------------------------------------------------------------------------->
  this.fromPixelX = function (x) {
    return x / xPixelFactor / g.absFactor.x;
  }

  //  --------------------------------------------------------------------------->
  this.fromPixelY = function (y) {
    return -(y - yPixelMax) / yPixelFactor / g.absFactor.y;
  }

  //  --------------------------------------------------------------------------->
  this.truePixelX = function (x) {
    return x / g.absFactor.x;
  }

  //  --------------------------------------------------------------------------->
  this.truePixelY = function (y) {
    return y / g.absFactor.y;
  }

  //  --------------------------------------------------------------------------->
  this.PixelPlot = function (xPixel, yPixel, down) {
    if (down) g.drawLine(xPixelOld, yPixelOld, xPixel, yPixel);
    xPixelOld = xPixel;
    yPixelOld = yPixel;
    return this;
  };

  //  --------------------------------------------------------------------------->
  this.SetPixelPos = function (xPixel, yPixel) {
    xPixelOld = xPixel;
    yPixelOld = yPixel;
    return this;
  };

  //  --------------------------------------------------------------------------->
  this.transformX = function(x) {
    if (x == null) return null;
    return this.toPixelX(this.NormX(x, false));
  }

  //  --------------------------------------------------------------------------->
  this.transformY = function(y) {
    if (y == null) return null;
    return this.toPixelY(this.NormY(y, false));
  }

  //  --------------------------------------------------------------------------->
  this.PixelLine = function (x1, y1, x2, y2) {
    g.drawLine(x1, y1, x2, y2);
    xPixelOld = x2;
    yPixelOld = y2;
  }

  //  --------------------------------------------------------------------------->
  this.NormX = function (x, isNewZero) {  // relative to absolute worldcoordinates
    if (x == null) return null;
    var xTotal = xZero + x;
    this.SetMinMaxX(xTotal);
    if (isNewZero) {
      xZero = xTotal;
      xOld = 0.0;
    } else
      xOld = x;
    return xTotal * factor;
  }

  //  --------------------------------------------------------------------------->
  this.NormY = function (y, isNewZero) {  // relative to absolute worldcoordinates
    if (y == null) return null;
    var yTotal = yZero + y;
    this.SetMinMaxY(yTotal);
    if (isNewZero) {
      yZero = yTotal;
      yOld = 0.0;
    } else
      yOld = y;
    return yTotal * factor;
  }

  //  --------------------------------------------------------------------------->
  this.unNormX = function (x) {
    return x / factor - xZero;
  }

  //  --------------------------------------------------------------------------->
  this.unNormY = function (y) {
    return y / factor - yZero;
  }

  //  --------------------------------------------------------------------------->
  this.toWorldX = function (x) {
    return this.unNormX(this.fromPixelX(x));
  }

  //  --------------------------------------------------------------------------->
  this.toWorldY = function (y) {
    return this.unNormY(this.fromPixelY(y));
  }

  //  --------------------------------------------------------------------------->
  //  Positionierung auf einen Welt-Koordinaten-Punkt, Stand : 19-Mrz-1986 
  this.SetPosition = function (X, Y, isNewZero) {
    SetPixelPos(this.toPixelX(this.NormX(X, isNewZero)), this.toPixelY(this.NormY(Y, isNewZero)));
    if (wordy) alert("SetPosition: X = " + X + ", Y = " + Y + ", isNewZero = " + isNewZero);
  }

  //  --------------------------------------------------------------------------->
  this.SetCenterPosition = function (isNewZero) {
    SetPosition(0.5 * xMax, 0.5 * yMax, isNewZero);
    if (wordy) alert("SetCenterPosition: X_Max = " + 0.5 * xMax + ", Y_Max = " + 0.5 * yMax + ", isNewZero = " + isNewZero);
  }

  // -----------------------------------------------------------------------------
  this.Plot = function (X, Y, Modus) {
    if (Math.abs(Modus) == 2) 
      return g.drawLine(xPixelOld, yPixelOld, this.toPixelX(this.NormX(X, (Modus < 0))), this.toPixelY(this.NormY(Y, (Modus < 0))));
    else SetPosition(X, Y, Modus < 0);
    if (wordy) {
      alert("Plot: X = " + X + ", Y = " + Y + "Modus = " + Modus);
    }
  }

  // -----------------------------------------------------------------------------
  this.drawImage = function (c, i, x, y) {
    return i.paintIcon(c, this.getGraphics(), this.toPixelX(this.NormX(x, false)) - i.getIconWidth() / 2, this.toPixelY(this.NormY(y, false)) - i.getIconHeight() / 2);
  }

  // -----------------------------------------------------------------------------
  this.drawImage = function (c, location, x, y) {
    var i = new ImageIcon(location);
    return drawImage(c, i, x, y);
  }

  // -----------------------------------------------------------------------------
  this.drawLine = function (X1, Y1, X2, Y2, LineModus, stroke, color, opacity) {
    return g.drawLine(this.toPixelX(this.NormX(X1, false)), this.toPixelY(this.NormY(Y1, false)), this.toPixelX(this.NormX(X2, false)), this.toPixelY(this.NormY(Y2, false)), stroke ? stroke : 1, color ? color : 'black', opacity ? opacity : 1.0);
  }

  // -----------------------------------------------------------------------------
  this.changeLine = function (node, X1, Y1, X2, Y2, LineModus, stroke, color, opacity) {
    return g.changeLine(node, this.toPixelX(this.NormX(X1, false)), 
                              this.toPixelY(this.NormY(Y1, false)), 
                              this.toPixelX(this.NormX(X2, false)), 
                              this.toPixelY(this.NormY(Y2, false)), stroke, color, opacity);
  }

  // -----------------------------------------------------------------------------
  this.drawLineColor = function (X1, Y1, X2, Y2, LineModus, wl1, wl2) {
      if (wordy) alert ("drawLineColor: (" + X1 + ", " + Y1 + ") " + wl1 + " nm, (" + X2 + ", " + Y2 + ") " + wl2 + " nm");
    var diff = (Math.abs(wl2 - wl1) + 0.001);
    var yDiff = (Math.abs(Y2 - Y1) + 0.001);
    var n = diff / incWL;
    var inc = incWL * ((wl2 - wl1) > 0.0 ? 1 : -1);
    var incY = yDiff / n * ((Y2 - Y1) > 0.0 ? 1 : -1);
    var wl = wl1;
    var y = Y1;
    var xOld = X1;
    var yOld = Y1;
    //   alert ("drawLineColor: (" + n + " incements, yDiff=" + yDiff + ") incWL=" + incWL + " nm, inc=" + inc + " nm");
    for (var i = 0; i <= n; i++) {
      y += incY;
      var x = walMath.calcZeroX(X1, Y1, X2, Y2, y);
      //     g.setColor (toColor (wl));
      //     alert (i + ": " + xOld + ", " + yOld + ") - (" + x + ", " + y + ") " + wl + " nm");
      g.drawLine(this.toPixelX(this.NormX(xOld, false)), this.toPixelY(this.NormY(yOld, false)), this.toPixelX(this.NormX(i == n ? X2 : x, false)), this.toPixelY(this.NormY(i == n ? Y2 : y, false)), 1, toColor(wl), 1.0);
      xOld = x;
      yOld = y;
      wl += inc;
    }
    if (wordy) {
      alert("drawLineColor : " + "X1 = " + X1 + ", Y1 = " + Y1 + ", X2 = " + X2 + ", Y2 = " + Y2);
    }
  }

  // ----------------------------------------------------------------------------->
  this.fillRect = function (x0, y0, x1, y1, color) {
    var wordy = false;
    var x = this.toPixelX(this.NormX(x0, false));
    var y = this.toPixelY(this.NormY(y1, false));
    var len = this.toPixelX(this.NormX(x1, false)) - x;
    var height = this.toPixelY(this.NormY(y0, false)) - y;
    g.drawRect(x, y, len, height, color, color, 1, 1.0);
    if (wordy) {
      alert("fillRect : " + "x = " + x + ", y = " + y + ", len = " + len + ", height = " + height);
    }
  }

  // -----------------------------------------------------------------------------
  this.SetBoldness = function (LineWidth) {
    this.lineWidth = LineWidth;
  }

  // -----------------------------------------------------------------------------
  this.GetBoldness = function () {
    return (lineWidth);
  }

  //  --------------------------------------------------------------------------->
  //  Zweck : PLOTTEN VON 'FETTEN' STRICHEN (DURCH MEHRFACH-ZEICHNUNG)
  //  Autor : Dr. Horst Walther, SiG Software Integration GmbH
  //  Stand : 13-Jan-1987
  //  --------------------------------------------------------------------------->
  //  XA, YA : AUSGANGSKoordinaten (werden mit Where erfragt)
  //  XB, YB : ZIELKoordinaten    (werden \uFFFDbergeben)
  //  MAL    : NUR UNGERADE UND BETRAGSMAESSIG GROESSER 2 SINNVOLL (?) -
  //           ENTSPRECH} OFT WIRD IM ABSTAND PL_LineWidth GEPLOTTET.
  //           >+1 - }EN WERDEN GERUNDET (VEKTOR UM 2*PL_LineWidth LAENGER)
  //           <-1 - }EN SIND ECKIG (VEKTORLAENGE UNVERA}ERT)
  //  --------------------------------------------------------------------------->
  this.drawBoldLine = function (XB, YB, Mal, color) {

    var SQRT3 = 1.732050807569;
    var
    M = 0,
      i = 0;
    var
    XA = 0.0,
      YA = 0.0,
      XC = 0.0,
      YC = 0.0,
      XD = 0.0,
      YD = 0.0,
      XS = 0.0,
      YS = 0.0,
      XY = 0.0,
      YX = 0.0,
      FX = 0.0,
      FY = 0.0,
      FXY = 0.0,
      DX = 0.0,
      DY = 0.0,
      FXS = 0.0,
      FYS = 0.0,
      FXC = 0.0,
      FXD = 0.0,
      FYC = 0.0,
      FYD = 0.0,
      SDL = 0.0;

    M = Math.abs(Mal);
    if (M > 1) {
      XA = GetPositionX();
      YA = GetPositionY();
      FXY = factor;
      Plot(XA, YA, 3);
      FX = FXY;
      FY = FXY;
      DX = (XB - XA) * FX;
      DY = (YB - YA) * FY;
      if ((Math.abs(DX) < 1.0E-10) && (Math.abs(DY) < 1E-10)) {
        DX = 1E-10;
      }
      SDL = lineWidth / Math.sqrt(DX * DX + DY * DY);
      XC = 0.5 * (DX + SQRT3 * DY) * SDL / FX;
      XD = 0.5 * (DX * SQRT3 + DY) * SDL / FX;
      XS = DY * SDL / FX;
      YC = 0.5 * (DX * SQRT3 - DY) * SDL / FY;
      YD = 0.5 * (DX - SQRT3 * DY) * SDL / FY;
      YS = DX * SDL / FY;
      XY = FX / FY;
      YX = FY / FX;
      M = M % 2;
      Plot(XB, YB, 2);
      for (var i = 1; i <= M; i++) {
        FXS = 1.0 * i * XS;
        FYS = 1.0 * i * YS;
        if ((Mal >= 0)) {
          FXC = 1.0 * i * XC;
          FXD = 1.0 * i * XD;
          FYC = 1.0 * i * YC;
          FYD = 1.0 * i * YD;
          Plot(XB + FXS, YB - FYS, 2);
          Plot(XB + FXC, YB - FYC, 2);
          Plot(XB + FXD, YB - FYD, 2);
          Plot(XB + FYS * YX, YB + FXS * XY, 2);
          Plot(XB + FYC * YX, YB + FXC * XY, 2);
          Plot(XB + FYD * YX, YB + FXD * XY, 2);
        }
        Plot(XB - FXS, YB + FYS, 2);
        Plot(XA - FXS, YA + FYS, 2);
        if ((Mal >= 0)) {
          Plot(XA - FXC, YA + FYC, 2);
          Plot(XA - FXD, YA + FYD, 2);
          Plot(XA - FYS * YX, YA - FXS * XY, 2);
          Plot(XA - FYC * YX, YA - FXC * XY, 2);
          Plot(XA - FYD * YX, YA - FXD * XY, 2);
        }
        Plot(XA + FXS, YA - FYS, 2);
        Plot(XB + FXS, YB - FYS, 2);
      }
      Plot(XB, YB, 3);
      /**nur damit WHERE richtig aufsetzt !!!*/
    } else {
      if ((M > 0)) {
        Plot(XB, YB, 2);
      } else {
        Plot(XB, YB, 3);
      }
    }
  }

  //  --------------------------------------------------------------------------->
  this.drawPixelPoint = function (x, y, color) {
    return g.drawRect(x, y, 1, 1, color, color, 1, 1.0);
  };

  //  --------------------------------------------------------------------------->
  /* Zweck : Zeichnen eines Kreuz-Symbols                                   */
  this.drawCrossDiag = function (X, Y, pixelSize, color) {
    g.drawLine(X - pixelSize, Y + pixelSize, X + pixelSize + 1, Y - pixelSize - 1, 1, color, 1.0);
    g.drawLine(X - pixelSize, Y - pixelSize, X + pixelSize + 1, Y + pixelSize + 1, 1, color, 1.0);
  }

  //  --------------------------------------------------------------------------->
  /* Zweck : Zeichnen eines Wye-Symbols                                     */
  this.drawWye = function (X, Y, pixelSize, color) {
    g.drawLine(X - pixelSize, Y - pixelSize, X, Y, 1, color, 1.0);
    g.drawLine(X + pixelSize, Y - pixelSize, X, Y, 1, color, 1.0);
    g.drawLine(X, Y, X, Y + pixelSize, 1, color, 1.0);
  }

  //  --------------------------------------------------------------------------->
  /* Zweck : Zeichnen eines Diamant-Symbols                                 */
  this.drawDiamond = function (X, Y, pixelSize, color) {
    g.drawLine(X - pixelSize, Y, X, Y - pixelSize - 1, 1, color, 1.0);
    g.drawLine(X, Y - pixelSize + 1, X + pixelSize, Y + 1, 1, color, 1.0);
    g.drawLine(X + pixelSize, Y + 1, X, Y + pixelSize, 1, color, 1.0);
    g.drawLine(X, Y + pixelSize, X - pixelSize, Y, 1, color, 1.0);
  }

  //  --------------------------------------------------------------------------->
  this.DrawPixelLine = function (X1, Y1, X2, Y2, stroke, color, opacity) {
    return g.drawLine(X1, Y1, X2, Y2, stroke, color, opacity);
  }

  //  --------------------------------------------------------------------------->
  //  Zweck : Zeichnen eines Kreis-Symbols
  this.drawCircleDirect = function (Xr, Yr, r, DirectModeLoc, color) {
    var n = 14;
    var X = new Array(0, 121, 239, 355, 465, 568, 663, 749, 823, 885, 935, 971, 993, 1000);
    var
    Xk1, Xk2, Yk1, Yk2, Xp1, Yp1, Xp2, Yp2, i;
    var Xfact = Math.abs((r * 0.001));
    var Yfact = Xfact;
    if (Xfact > 0.0) {
      Xk1 = (X[0] * Xfact + 0.5);
      Yk1 = (X[n - 1] * Yfact + 0.5);
      for (var i = 1; i < n; i++) {
        Xk2 = (X[i] * Xfact + 0.5);
        Yk2 = (X[n - i] * Yfact + 0.5);
        Xp1 = Xr - Xk1;
        Yp1 = Yr + Yk1;
        Xp2 = Xr - Xk2;
        Yp2 = Yr + Yk2;
        this.DrawPixelLine(Xp1, Yp1, Xp2, Yp2, 1, color, 1.0);
        Xp1 = Xr + Xk1;
        Xp2 = Xr + Xk2;
        this.DrawPixelLine(Xp1, Yp1, Xp2, Yp2, 1, color, 1.0);
        Yp1 = Yr - Yk1;
        Yp2 = Yr - Yk2;
        this.DrawPixelLine(Xp1, Yp1 + 1, Xp2, Yp2 + 1, 1, color, 1.0);
        Xp1 = Xr - Xk1;
        Xp2 = Xr - Xk2;
        this.DrawPixelLine(Xp1, Yp1 + 1, Xp2, Yp2 + 1, 1, color, 1.0);
        Xk1 = Xk2;
        Yk1 = Yk2;
      }
    }
  }

  // ---------------------------------------------------------------------------->
  this.drawCross = function (X1, Y1, pixelSize, color) {
    g.drawLine(X1 - pixelSize, Y1, X1 + pixelSize + 2, Y1, 1, color, 1.0);
    g.drawLine(X1, Y1 - pixelSize, X1, Y1 + pixelSize + 1, 1, color, 1.0);
  }

  // ---------------------------------------------------------------------------->
  this.drawStar = function (X, Y, pixelSize, color) {
    g.drawLine(X - pixelSize, Y + pixelSize, X + pixelSize + 1, Y - pixelSize - 1, 1, color, 1.0);
    g.drawLine(X - pixelSize, Y - pixelSize, X + pixelSize + 1, Y + pixelSize + 1, 1, color, 1.0);
    g.drawLine(X - pixelSize - 2, Y, X + pixelSize + 4, Y, 1, color, 1.0);
  }

  // -----------------------------------------------------------------------------
  this.DrawSquare = function (X1, Y1, X2, Y2, color) {
    if (!fill) {
      g.drawLine(X1, Y1, X2, Y1, 1, color, 1.0);
      g.drawLine(X2, Y1, X2, Y2, 1, color, 1.0);
      g.drawLine(X1, Y2, X2, Y2, 1, color, 1.0);
      g.drawLine(X1, Y2, X1, Y1, 1, color, 1.0);
    } else
      for (var i = Y2; i <= Y1; i++)
        g.drawLine(X1, i, X2, i, 1, color, 1.0);
  }

  //  --------------------------------------------------------------------------->
  this.drawCircle = function (X_R, Y_R, Xradius, color, opacity, id) {
    return g.drawCircle (this.toPixelX(this.NormX(X_R, false)), this.toPixelY(this.NormY(Y_R, false)), this.toPixelX(this.NormX(Xradius)), color, opacity, id); 
  }

  //  --------------------------------------------------------------------------->
  this.changeCircle = function (node, X_R, Y_R, Xradius, color, opacity, id) {
    return g.changeCircle (node, this.toPixelX(this.NormX(X_R, false)), this.toPixelY(this.NormY(Y_R, false)), this.toPixelX(this.NormX(Xradius)), color, opacity, id); 
  }

  //  --------------------------------------------------------------------------->
  this.drawSymbol = function (X, Y, symType, pixelSize, stroke, color, opacity) {
  if (wordy) alert (this.id+'.drawSymbol ('+X+', '+Y+', '+symType+', '+pixelSize+', '+stroke+', '+color+', '+opacity+')');
    var node;
    var xPixel = this.toPixelX(this.NormX(X, false));
    var yPixel = this.toPixelY(this.NormY(Y, false));
    if (!stroke) stroke = 1;
    if (!color) color = 'black';
    if (!opacity) opacity = 1.0;
    switch (symType) {
    case 1:
      node = this.drawCross(xPixel, yPixel, pixelSize);
      break;
    case 2:
      node = this.drawCrossDiag(xPixel, yPixel, pixelSize);
      break;
    case 3:
      node = g.drawRect(xPixel - pixelSize, yPixel + pixelSize, pixelSize * 2, pixelSize * 2, color, color, stroke, 0.0);
      break;
    case 4:
      node = g.drawRect(xPixel - pixelSize, yPixel + pixelSize, pixelSize * 2, pixelSize * 2, color, color, stroke, 1.0);
      break;
    case 5:
      node = this.drawDiamond(xPixel, yPixel, pixelSize);
      break;
    case 6:
      node = this.drawWye(xPixel, yPixel, pixelSize + 1);
      break;
    case 7:
      node = this.drawStar(xPixel, yPixel, pixelSize);
      break;
    case 8:
      node = g.drawCircle(xPixel, yPixel, pixelSize, color, opacity);
      break;
    case 9:
      node = g.fillCircle(xPixel, yPixel, pixelSize, color, opacity);
      break;
    case 10:
      node = g.drawLine(xPixel, yPixel - pixelSize, xPixel, yPixel + pixelSize, stroke, color, opacity);
      break;
    default:
      node = g.drawLine(xPixel, yPixel - pixelSize, xPixel, yPixel + pixelSize, stroke, color, opacity);
      break;
    }
    xPixelOld = xPixel;
    yPixelOld = yPixel;
    return node;
  }

  //  --------------------------------------------------------------------------->
  this.changeSymbol = function (node, X, Y, symType, pixelSize, stroke, color, opacity) {
  if (wordy) alert (this.id+'.changeSymbol ('+node.id+', '+X+', '+Y+', '+symType+', '+pixelSize+', '+stroke+', '+color+', '+opacity+')');
    var xPixel = this.toPixelX(this.NormX(X, false));
    var yPixel = this.toPixelY(this.NormY(Y, false));
    switch (symType) {
    case 1:
      alert('change drawCross (xPixel, yPixel, pixelSize) not yet implemented');
      break;
    case 2:
      alert('change drawCrossDiag (xPixel, yPixel, pixelSize) not yet implemented');
      break;
    case 3:
      node = g.changeRect(xPixel - pixelSize, yPixel + pixelSize, pixelSize * 2, pixelSize * 2, color, color, stroke, 0.0);
      break;
    case 4:
      node = g.changeRect(xPixel - pixelSize, yPixel + pixelSize, pixelSize * 2, pixelSize * 2, color, color, stroke, 1.0);
      break;
    case 5:
      alert('change Diamond (xPixel, yPixel, pixelSize) not yet implemented');
      break;
    case 6:
      alert('change Wye (xPixel, yPixel, pixelSize + 1) not yet implemented');
      break;
    case 7:
      alert('change Star (xPixel, yPixel, pixelSize) not yet implemented');
      break;
    case 8:
      node = g.changeCircle(node, xPixel, yPixel, pixelSize, color, opacity);
      break;
    case 9:
      node = g.changeCircle(node, xPixel, yPixel, pixelSize, color, opacity);
      break;
    case 10:
      alert('change Line (xPixel, yPixel - pixelSize, xPixel, yPixel + pixelSize) not yet implemented');
      break;
    default:
      alert('change Symbol ('+xPixel+', '+yPixel+' - '+pixelSize+', '+xPixel+', '+yPixel+' + '+pixelSize+') not yet implemented');
    }
    if (xPixel != null) xPixelOld = xPixel;
    if (yPixel != null) yPixelOld = yPixel;
    return node;
  }

//  ----------------------------------------------------------------------------
  this.pixelShift = function(node, cx, cy) {
    return g.pixelShift (node, cx, cy);    
  }

  //  --------------------------------------------------------------------------->
  this.getOffScreenImage = function () {
    return this.offScreenImage;
  }

  //  --------------------------------------------------------------------------->
  this.save = function (name) {
    //  imageIO.saveImage (getOffScreenImage (), name);
    alert('*** warning: save (' + name + ') not yet implemented');
    return this;
  }

  //  --------------------------------------------------------------------------->
  this.getOffScreenGraphics = function () {
    return g;
  }

  //  --------------------------------------------------------------------------->
  this.getScreenCenter = function () {
    var d = new Position2d(Toolkit.getDefaultToolkit().getScreenSize());
    d.width *= 0.5;
    d.height *= 0.5;
    return d;
  }

  //  --------------------------------------------------------------------------->
  this.getScreenSize = function () {
    return Toolkit.getDefaultToolkit().getScreenSize();
  }

  //  --------------------------------------------------------------------------->
  this.centerFrame = function (frame) {
    var d = new Position2d(Toolkit.getDefaultToolkit().getScreenSize());
    frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2);
    return this;
  }

  //  --------------------------------------------------------------------------->
  this.drawBoxPixel = function (x0, y0, width, height, color, strokeColor, stroke, opacity) {
    return g.drawRect(x0, y0, width, height, color, strokeColor, stroke, opacity);
  }; /**/

  //  --------------------------------------------------------------------------->
  this.drawBox = function (x0, y0, width, height, color, strokeColor, stroke, opacity) {
    return g.drawRect(this.toPixelX(this.NormX(x0, false)), this.toPixelY(this.NormY(y0, false)), this.toPixelX(this.NormX(width, false)), this.toPixelY(this.NormY(height, false)), color, strokeColor, stroke, opacity);
    //drawLine (x0, y0   , x0, y0+height, 0);
    //drawLine (x0, y0+height, x0+len, y0+height, 0);
    //drawLine (x0+len, y0+height, x0+len, y0   , 0);
    //drawLine (x0+len, y0   , x0 , y0   , 0);
  };

  //  --------------------------------------------------------------------------->
  this.drawMaxBox = function (g) {
    g.drawLine(0, 0, 0, yPixelMax);
    g.drawLine(0, yPixelMax, xPixelMax, yPixelMax);
    g.drawLine(xPixelMax, yPixelMax, xPixelMax, 0);
    g.drawLine(xPixelMax, 0, 0, 0);
    return this;
  }

  //  --------------------------------------------------------------------------->
  this.drawMaxCross = function (g) {
    g.drawLine(0, 0, xPixelMax, yPixelMax);
    g.drawLine(xPixelMax, 0, 0, yPixelMax);
    return this;
  }

  //  --------------------------------------------------------------------------->
  this.saveColor = function (g) {
    tmpColor = g.getColor();
  }

  //  --------------------------------------------------------------------------->
  this.restoreColor = function (g) {
    g.setColor(tmpColor);
    return this;
  }

  //  --------------------------------------------------------------------------->
  var minLen = 380,
    maxLen = 780;

  //  --------------------------------------------------------------------------->
  this.getMinWaveLength = function () {
    return (minLen);
  }

  //  --------------------------------------------------------------------------->
  this.getMaxWaveLength = function () {
    return (maxLen);
  }

  //  --------------------------------------------------------------------------->
  //  CIE 1931 chromaticity coordinates of spectral stimuli (only xy, z = 1 - x - y)
  //  Rogers, David F., "Procedural Elements for Computer Graphics, " McGraw-Hill Book Company, New York, 1985, pp390-398.
  this.toColour = function (waveLength) {
    var spectrum_xy = new Array(
    new Array(0.1741, 0.0050), new Array(0.1740, 0.0050), new Array(0.1738, 0.0049), new Array(0.1736, 0.0049), new Array(0.1733, 0.0048), new Array(0.1730, 0.0048), new Array(0.1726, 0.0048), new Array(0.1721, 0.0048), new Array(0.1714, 0.0051), new Array(0.1703, 0.0058), new Array(0.1689, 0.0069), new Array(0.1669, 0.0086), new Array(0.1644, 0.0109), new Array(0.1611, 0.0138), new Array(0.1566, 0.0177), new Array(0.1510, 0.0227), new Array(0.1440, 0.0297), new Array(0.1355, 0.0399), new Array(0.1241, 0.0578), new Array(0.1096, 0.0868), new Array(0.0913, 0.1327), new Array(0.0687, 0.2007), new Array(0.0454, 0.2950), new Array(0.0235, 0.4127), new Array(0.0082, 0.5384), new Array(0.0039, 0.6548), new Array(0.0139, 0.7502), new Array(0.0389, 0.8120), new Array(0.0743, 0.8338), new Array(0.1142, 0.8262), new Array(0.1547, 0.8059), new Array(0.1929, 0.7816), new Array(0.2296, 0.7543), new Array(0.2658, 0.7243), new Array(0.3016, 0.6923), new Array(0.3373, 0.6589), new Array(0.3731, 0.6245), new Array(0.4087, 0.5896), new Array(0.4441, 0.5547), new Array(0.4788, 0.5202), new Array(0.5125, 0.4866), new Array(0.5448, 0.4544), new Array(0.5752, 0.4242), new Array(0.6029, 0.3965), new Array(0.6270, 0.3725), new Array(0.6482, 0.3514), new Array(0.6658, 0.3340), new Array(0.6801, 0.3197), new Array(0.6915, 0.3083), new Array(0.7006, 0.2993), new Array(0.7079, 0.2920), new Array(0.7140, 0.2859), new Array(0.7190, 0.2809), new Array(0.7230, 0.2770), new Array(0.7260, 0.2740), new Array(0.7283, 0.2717), new Array(0.7300, 0.2700), new Array(0.7311, 0.2689), new Array(0.7320, 0.2680), new Array(0.7327, 0.2673), new Array(0.7334, 0.2666), new Array(0.7340, 0.2660), new Array(0.7344, 0.2656), new Array(0.7346, 0.2654), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653), new Array(0.7347, 0.2653));
    if (waveLength < minLen || waveLength > maxLen) {
      show('trace', "### err: " + " (" + waveLength + "): Wavelength () out of visible ligtht range (" + minLen + " nm - " + maxLen + " nm)");
      waveLength = waveLength < minLen ? minLen : waveLength > maxLen ? maxLen : waveLength;
    }
    var i = Math.round((waveLength - minLen) / 400 * 81);
    //if (wordy)
    //	  alert (waveLength+' 0 < '+i+' < '+spectrum_xy.length);
    show('trace', i + ": " + spectrum_xy[i][0] * 255 + ", " + spectrum_xy[i][1] * 255 + ", " + (1.0 - spectrum_xy[i][0] - spectrum_xy[i][1]) * 255);
    return new Array(spectrum_xy[i][0] * 255, spectrum_xy[i][1] * 255, Math.abs(1.0 - spectrum_xy[i][0] - spectrum_xy[i][1]) * 255, 1.0);
  }

  //  --------------------------------------------------------------------------->
  this.toColor = function (WL) {
    //
    //  RGB VALUES FOR VISIBLE WAVELENGTHS   by Dan Bruton (astro@tamu.edu)
    //  This program can be found at http://www.physics.sfasu.edu/astro/color.html
    //  and was last updated on February 20, 1996.
    //  This program will create approximate RGB values for given visible
    //  wavelengths between 380 nm and 780 nm. The red, green and blue values (RGB)
    //  are assumed to vary linearly with wavelength (for GAMMA=1).
    var wordy = false;
    //    var minLen = 380, maxLen = 780;
    var GAMMA = 0.80,
      R = 0.0,
      G = 0.0,
      B = 0.0,
      SSS = 0.0;

    //  WL = 380.0 + (i * 400.0 / M);//     WAVELENGTH = WL
    if (WL < minLen || WL > maxLen) {
      if (wordy) {
        alert("### err: " + " (" + WL + "): Wavelength () out of visible ligtht range (" + minLen + " nm - " + maxLen + " nm)");
        return SIG_OCKER;
      } else WL = WL < minLen ? minLen : WL > maxLen ? maxLen : WL;
    }

    if ((WL >= 380.) && (WL <= 440.)) {
      R = -1. * (WL - 440.) / (440. - 380.);
      G = 0.0;
      B = 1.0;
    }
    if ((WL >= 440.) && (WL <= 490.)) {
      R = 0.0;
      G = (WL - 440.) / (490. - 440.);
      B = 1.0;
    }
    if ((WL >= 490.) && (WL <= 510.)) {
      R = 0.0;
      G = 1.0;
      B = -1. * (WL - 510.) / (510. - 490.);
    }
    if ((WL >= 510.) && (WL <= 580.)) {
      R = (WL - 510.) / (580. - 510.);
      G = 1.0;
      B = 0.0;
    }
    if ((WL >= 580.) && (WL <= 645.)) {
      R = 1.0;
      G = -1. * (WL - 645.) / (645. - 580.);
      B = 0.0;
    }
    if ((WL >= 645.) && (WL <= 780.)) {
      R = 1.0;
      G = 0.0;
      B = 0.0;
    }

    //  LET THE INTENSITY SSS FALL OFF NEAR THE VISION LIMITS
    if (WL > 700.) {
      SSS = .3 + .7 * (780. - WL) / (780. - 700.);
    } else if (WL < 420.) {
      SSS = .3 + .7 * (WL - 380.) / (420. - 380.);
    } else SSS = 1.0;

    //  GAMMA ADJUST AND WRITE IMAGE TO AN ARRAY
    R = Math.pow((SSS * R), GAMMA);
    G = Math.pow((SSS * G), GAMMA);
    B = Math.pow((SSS * B), GAMMA);

    if (wordy) show('trace', "R=" + R + ", G=" + G + ", B=" + B);

    //    return Color (R*255, G*255, B*255, SSS);
    return new Array(R * 255, G * 255, B * 255, SSS);
  }

  //  --------------------------------------------------------------------------->
  this.showStatus = function () {
    alert('plot2d is ' + this.status + '!');
  }

  //  --------------------------------------------------------------------------->
  this.PathData = function (d) {
    var dataArray = d;

    this.transform = function () {
      for (var i=0; i< dataArray.length; i++)
        dataArray[i] = dataArray[i].transform();
      return this;
    }

    this.toString = function () {
      var d = '';
      for (var i=0; i< dataArray.length; i++)
        d += (dataArray[i].toString()+ ' ');
//      alert (d);
      return d;
    }
    return this;
  }

//  ----------------------------------------------------------------------------
  this.moveTo = function (p, isRelative) {
    var classId = 'M'; 

    this.transform = function() {
      p = p.transform();
      return this;
    }

    this.toString = function() {
      return (isRelative ? classId.toLowerCase() : classId) + BLANK + p.toString() + BLANK;
    }
    return this;
  }

//  ----------------------------------------------------------------------------
  this.lineTo = function (p, isRelative) {
    var classId = 'L'; 

    this.transform = function() {
      p = p.transform();
      return this;
    }

    this.toString = function() {
      return (isRelative ? classId.toLowerCase() : classId) + BLANK + p.toString() + BLANK;
    }
    return this;
  }

//  ----------------------------------------------------------------------------
  this.horLineTo = function (x, isRelative) {
    classId = 'H'; 

    this.transform = function() {
      x = this.transformX(x);
      return this;
    }

    this.toString = function() {
      return (isRelative ? classId.toLowerCase() : classId) + BLANK + x + BLANK;
    }
    return this;
  }

//  ----------------------------------------------------------------------------
  this.vertLineTo = function (y, isRelative) {
    var classId = 'V'; 

    this.transform = function() {
      y = this.transformY(y);
      return this;
    }

    this.toString = function() {
      return (isRelative ? classId.toLowerCase() : classId) + BLANK + y + BLANK;
    }
    return this;
  }

//  ----------------------------------------------------------------------------
  this.curveTo = function (p1, p2, p3, isRelative) {
    var classId = 'C'; 

    this.transform = function() {
      p1 = p1.transform();
      p2 = p2.transform();
      p3 = p3.transform();
      return this;
    }

    this.toString = function() {
      return (isRelative ? classId.toLowerCase() : classId) + BLANK + p1.toString() + BLANK + p2.toString() + BLANK + p3.toString() + BLANK;
    }
    return this;
  }

//  ----------------------------------------------------------------------------
  this.smoothCurveTo = function (p1, p2, isRelative) {
    var classId = 'S'; 

    this.transform = function() {
      p1 = p1.transform();
      p2 = p2.transform();
      return this;
    }

    this.toString = function() {
      return (isRelative ? classId.toLowerCase() : classId) + BLANK + p1.toString() + BLANK + p2.toString() + BLANK;
    }
    return this;
  }

//  ----------------------------------------------------------------------------
  this.quadBelzierTo = function (p, isRelative) {
    var classId = 'Q'; 

    this.transform = function() {
      p = p.transform();
      return this;
    }

    this.toString = function() {
      return (isRelative ? classId.toLowerCase() : classId) + BLANK + p1.toString() + BLANK + p2.toString() + BLANK;
    }
    return this;
  }

//  ----------------------------------------------------------------------------
  this.smoothBelzierTo = function (p, isRelative) {
    var classId = 'T'; 

    this.transform = function() {
      p = p.transform();
      return this;
    }

    this.toString = function() {
      return (isRelative ? classId.toLowerCase() : classId) + BLANK + p.toString() + BLANK;
    }
    return this;
  }

//  ----------------------------------------------------------------------------
  this.arcTo = function (r1, r2, xAxisRotation, largeArcFlag, sweepFlag, p, isRelative) {
    var classId = 'A'; 

    this.transform = function() {
      r1 = p2d.toPixelX (r1);
      r2 = p2d.toPixelY (r2);
      p = p.transform();
      return this;
    }

    this.toString = function() {
      return (isRelative ? classId.toLowerCase() : classId) + BLANK + r1 + BLANK + r2 + BLANK + xAxisRotation + BLANK + largeArcFlag + BLANK + sweepFlag + BLANK + p + BLANK;
    }
    return this;
  }

//  ----------------------------------------------------------------------------
  this.closePath = function (p, isRelative) {
    var classId = 'Z'; 

    this.transform = function() {
      return this;
    }

    this.toString = function() {
      return (isRelative ? classId.toLowerCase() : classId) + BLANK;
    }
    return this;
  }

  //  --------------------------------------------------------------------------->
  this.setPath = function (id, pathData, stroke, fill, strokeWidth, transform) {
    x = 0; y = 0;
    return g.setPath (id, pathData.transform().toString(), stroke, fill, strokeWidth, transform);
  }

  //  --------------------------------------------------------------------------->
  this.setTextPath = function (id, xlinkHref, startOffset) {
    return g.setTextPath (id, xlinkHref, startOffset);
  }

  //  --------------------------------------------------------------------------->
  this.drawText = function (x, y, s, dx, dy, fontSize, color, fontWeight, fontName, anchor, textPath) {
    return g.drawText(this.toPixelX(this.NormX(x, false)), this.toPixelY(this.NormY(y, false)), s, dx, dy, fontSize, color, fontWeight, fontName, anchor, textPath);
  };

  //  ---------------------------------------------------------------------------
  this.changeText = function (node, x, y, s, dx, dy, fontSize, color, anchor) {
    return g.changeText(node, this.toPixelX(this.NormX(x, false)), this.toPixelY(this.NormY(y, false)), s, dx, dy, fontSize, color, anchor);
  };

  //  ----------------------------------------------------------------------------
  this.makeContainer = function (id) {
    return g.makeContainer(id);
  };

//  ----------------------------------------------------------------------------
  this.scale = function (id, factorX, factorY) {
    return g.scale(id, factorX, factorY);
  }

  //  ----------------------------------------------------------------------------
  this.enterContainer = function (node) {
    return g.enterContainer(node);
  }

  //  ----------------------------------------------------------------------------
  this.leaveContainer = function () {
    return g.leaveContainer();
  }

//  -------------------------------------------------------------------------->
  this.add = function (node) {
    return g.add (node);
  };

  //  ----------------------------------------------------------------------------
  this.getBackGroundNode = function () {
    return g.getBackGroundNode();
  }

//  --------------------------------------------------------------------------->

  this.maxSize = getMaxSize ();
  fill = fill==undefined ? '#ffffff' : fill;
  opacity = opacity==undefined ? this.opacity : opacity;
  var p = this;
  window.onresize = function () {p.resize (p)};
  try {
    var g = new svgJs().init (window, id, width, height, fill, opacity);
    var opsMode = this.SVG = 'svg';
  } catch (e) {
    var g = new jsGraphics().init(window, id, width, height, fill, opacity)
  }
    var opsMode = this.DOM = 'DOM';
  this.walMath = new WalMath();
  var p2d = this;

//  --------------------------------------------------------------------------->
}
