Data collection and display system (Collect a data item periodically (ex. temperature, value of stock), by any means (ex, type in, read file, get online), present the information in tabular/graphical...

1 answer below »



  • Data collection and display system (Collect a data item periodically (ex. temperature, value of stock), by any means (ex, type in, read file, get online), present the information in tabular/graphical form, store the information for later recall)




  • Read an html file and count the number of tags of each type, (ex, 1 , 1 , 2 ...), flag missing end tags and pretty format with configurable indentation spaces (ex. 0 spaces for , 2 spaces for ...)




  • Keyboard piano, each key on a row shall produce a tone corresponding to a piano key. Program can store a file of keys/tones produced when a particular key or key combination (ex. PF10, Ctrl+R) is pressed to start and stop the file 'recording'.






Untitled document ● Data collection and display system (Collect a data item periodically (ex. temperature, value of stock), by any means (ex, type in, read file, get online), present the information in tabular/graphical form, store the information for later recall) ● Read an html file and count the number of tags of each type, (ex, 1 , 1 , 2 ...), flag missing end tags and pretty format with configurable indentation spaces (ex. 0 spaces for , 2 spaces for ...) ● Keyboard piano, each key on a row shall produce a tone corresponding to a piano key. Program can store a file of keys/tones produced when a particular key or key combination (ex. PF10, Ctrl+R) is pressed to start and stop the file 'recording'.
Answered 2 days AfterJul 21, 2021

Answer To: Data collection and display system (Collect a data item periodically (ex. temperature, value of...

Karthi answered on Jul 24 2021
142 Votes
cpp/pbPlots.cpp
cpp/pbPlots.cpp
// Downloaded from https://repo.progsbase.com - Code Developed Using progsbase.
#include "pbPlots.hpp"
using namespace std;
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
bool CropLineWithinBoundary(NumberReference *x1Ref, NumberReference *y1Ref, NumberReference *x2Ref, NumberReference *y2Ref, double xMin, double xMax, double yMin, double yMax){
  double x1, y1, x2, y2;
  bool success, p1In, p2In;
  double dx, dy, f1, f2, f3, f4, f;
  x1 = x1Ref->numberValue;
  y1 = y1Ref->numberValue;
  x2 = x2Ref->numberValue;
  y2 = y2Ref->numberValue;
  p1In = x1 >= xMin && x1 <= xMax && y1 >= yMin && y1 <= yMax;
  p2In = x2 >= xMin && x2 <= xMax && y2 >= yMin && y2 <= yMax;
  if(p1In && p2In){
    success = true;
  }else if( !p1In  && p2In){
    dx = x1 - x2;
    dy = y1 - y2;
    if(dx != 0.0){
      f1 = (xMin - x2)/dx;
      f2 = (xMax - x2)/dx;
    }else{
      f1 = 1.0;
      f2 = 1.0;
    }
    if(dy != 0.0){
      f3 = (yMin - y2)/dy;
      f4 = (yMax - y2)/dy;
    }else{
      f3 = 1.0;
      f4 = 1.0;
    }
    if(f1 < 0.0){
      f1 = 1.0;
    }
    if(f2 < 0.0){
      f2 = 1.0;
    }
    if(f3 < 0.0){
      f3 = 1.0;
    }
    if(f4 < 0.0){
      f4 = 1.0;
    }
    f = fmin(f1, fmin(f2, fmin(f3, f4)));
    x1 = x2 + f*dx;
    y1 = y2 + f*dy;
    success = true;
  }else if(p1In &&  !p2In ){
    dx = x2 - x1;
    dy = y2 - y1;
    if(dx != 0.0){
      f1 = (xMin - x1)/dx;
      f2 = (xMax - x1)/dx;
    }else{
      f1 = 1.0;
      f2 = 1.0;
    }
    if(dy != 0.0){
      f3 = (yMin - y1)/dy;
      f4 = (yMax - y1)/dy;
    }else{
      f3 = 1.0;
      f4 = 1.0;
    }
    if(f1 < 0.0){
      f1 = 1.0;
    }
    if(f2 < 0.0){
      f2 = 1.0;
    }
    if(f3 < 0.0){
      f3 = 1.0;
    }
    if(f4 < 0.0){
      f4 = 1.0;
    }
    f = fmin(f1, fmin(f2, fmin(f3, f4)));
    x2 = x1 + f*dx;
    y2 = y1 + f*dy;
    success = true;
  }else{
    success = false;
  }
  x1Ref->numberValue = x1;
  y1Ref->numberValue = y1;
  x2Ref->numberValue = x2;
  y2Ref->numberValue = y2;
  return success;
}
double IncrementFromCoordinates(double x1, double y1, double x2, double y2){
  return (x2 - x1)/(y2 - y1);
}
double InterceptFromCoordinates(double x1, double y1, double x2, double y2){
  double a, b;
  a = IncrementFromCoordinates(x1, y1, x2, y2);
  b = y1 - a*x1;
  return b;
}
vector *Get8HighContrastColors(){
  vector *colors;
  colors = new vector (8.0);
  colors->at(0) = CreateRGBColor(3.0/256.0, 146.0/256.0, 206.0/256.0);
  colors->at(1) = CreateRGBColor(253.0/256.0, 83.0/256.0, 8.0/256.0);
  colors->at(2) = CreateRGBColor(102.0/256.0, 176.0/256.0, 50.0/256.0);
  colors->at(3) = CreateRGBColor(208.0/256.0, 234.0/256.0, 43.0/256.0);
  colors->at(4) = CreateRGBColor(167.0/256.0, 25.0/256.0, 75.0/256.0);
  colors->at(5) = CreateRGBColor(254.0/256.0, 254.0/256.0, 51.0/256.0);
  colors->at(6) = CreateRGBColor(134.0/256.0, 1.0/256.0, 175.0/256.0);
  colors->at(7) = CreateRGBColor(251.0/256.0, 153.0/256.0, 2.0/256.0);
  return colors;
}
void DrawFilledRectangleWithBorder(RGBABitmapImage *image, double x, double y, double w, double h, RGBA *borderColor, RGBA *fillColor){
  if(h > 0.0 && w > 0.0){
    DrawFilledRectangle(image, x, y, w, h, fillColor);
    DrawRectangle1px(image, x, y, w, h, borderColor);
  }
}
RGBABitmapImageReference *CreateRGBABitmapImageReference(){
  RGBABitmapImageReference *reference;
  reference = new RGBABitmapImageReference();
  reference->image = new RGBABitmapImage();
  reference->image->x = new vector (0.0);
  return reference;
}
bool RectanglesOverlap(Rectangle *r1, Rectangle *r2){
  bool overlap;
  overlap = false;
  overlap = overlap || (r2->x1 >= r1->x1 && r2->x1 <= r1->x2 && r2->y1 >= r1->y1 && r2->y1 <= r1->y2);
  overlap = overlap || (r2->x2 >= r1->x1 && r2->x2 <= r1->x2 && r2->y1 >= r1->y1 && r2->y1 <= r1->y2);
  overlap = overlap || (r2->x1 >= r1->x1 && r2->x1 <= r1->x2 && r2->y2 >= r1->y1 && r2->y2 <= r1->y2);
  overlap = overlap || (r2->x2 >= r1->x1 && r2->x2 <= r1->x2 && r2->y2 >= r1->y1 && r2->y2 <= r1->y2);
  return overlap;
}
Rectangle *CreateRectangle(double x1, double y1, double x2, double y2){
  Rectangle *r;
  r = new Rectangle();
  r->x1 = x1;
  r->y1 = y1;
  r->x2 = x2;
  r->y2 = y2;
  return r;
}
void CopyRectangleValues(Rectangle *rd, Rectangle *rs){
  rd->x1 = rs->x1;
  rd->y1 = rs->y1;
  rd->x2 = rs->x2;
  rd->y2 = rs->y2;
}
void DrawXLabelsForPriority(double p, double xMin, double oy, double xMax, double xPixelMin, double xPixelMax, NumberReference *nextRectangle, RGBA *gridLabelColor, RGBABitmapImage *canvas, vector *xGridPositions, StringArrayReference *xLabels, NumberArrayReference *xLabelPriorities, vector *occupied, bool textOnBottom){
  bool overlap, currentOverlaps;
  double i, j, x, px, padding;
  vector *text;
  Rectangle *r;
  r = new Rectangle();
  padding = 10.0;
  overlap = false;
  for(i = 0.0; i < xLabels->stringArray->size(); i = i + 1.0){
    if(xLabelPriorities->numberArray->at(i) == p){
      x = xGridPositions->at(i);
      px = MapXCoordinate(x, xMin, xMax, xPixelMin, xPixelMax);
      text = xLabels->stringArray->at(i)->string;
      r->x1 = floor(px - GetTextWidth(text)/2.0);
      if(textOnBottom){
        r->y1 = floor(oy + 5.0);
      }else{
        r->y1 = floor(oy - 20.0);
      }
      r->x2 = r->x1 + GetTextWidth(text);
      r->y2 = r->y1 + GetTextHeight(text);
      /* Add padding */
      r->x1 = r->x1 - padding;
      r->y1 = r->y1 - padding;
      r->x2 = r->x2 + padding;
      r->y2 = r->y2 + padding;
      currentOverlaps = false;
      for(j = 0.0; j < nextRectangle->numberValue; j = j + 1.0){
        currentOverlaps = currentOverlaps || RectanglesOverlap(r, occupied->at(j));
      }
      if( !currentOverlaps  && p == 1.0){
        DrawText(canvas, r->x1 + padding, r->y1 + padding, text, gridLabelColor);
        CopyRectangleValues(occupied->at(nextRectangle->numberValue), r);
        nextRectangle->numberValue = nextRectangle->numberValue + 1.0;
      }
      overlap = overlap || currentOverlaps;
    }
  }
  if( !overlap  && p != 1.0){
    for(i = 0.0; i < xGridPositions->size(); i = i + 1.0){
      x = xGridPositions->at(i);
      px = MapXCoordinate(x, xMin, xMax, xPixelMin, xPixelMax);
      if(xLabelPriorities->numberArray->at(i) == p){
        text = xLabels->stringArray->at(i)->string;
        r->x1 = floor(px - GetTextWidth(text)/2.0);
        if(textOnBottom){
          r->y1 = floor(oy + 5.0);
        }else{
          r->y1 = floor(oy - 20.0);
        }
        r->x2 = r->x1 + GetTextWidth(text);
        r->y2 = r->y1 + GetTextHeight(text);
        DrawText(canvas, r->x1, r->y1, text, gridLabelColor);
        CopyRectangleValues(occupied->at(nextRectangle->numberValue), r);
        nextRectangle->numberValue = nextRectangle->numberValue + 1.0;
      }
    }
  }
}
void DrawYLabelsForPriority(double p, double yMin, double ox, double yMax, double yPixelMin, double yPixelMax, NumberReference *ne
xtRectangle, RGBA *gridLabelColor, RGBABitmapImage *canvas, vector *yGridPositions, StringArrayReference *yLabels, NumberArrayReference *yLabelPriorities, vector *occupied, bool textOnLeft){
  bool overlap, currentOverlaps;
  double i, j, y, py, padding;
  vector *text;
  Rectangle *r;
  r = new Rectangle();
  padding = 10.0;
  overlap = false;
  for(i = 0.0; i < yLabels->stringArray->size(); i = i + 1.0){
    if(yLabelPriorities->numberArray->at(i) == p){
      y = yGridPositions->at(i);
      py = MapYCoordinate(y, yMin, yMax, yPixelMin, yPixelMax);
      text = yLabels->stringArray->at(i)->string;
      if(textOnLeft){
        r->x1 = floor(ox - GetTextWidth(text) - 10.0);
      }else{
        r->x1 = floor(ox + 10.0);
      }
      r->y1 = floor(py - 6.0);
      r->x2 = r->x1 + GetTextWidth(text);
      r->y2 = r->y1 + GetTextHeight(text);
      /* Add padding */
      r->x1 = r->x1 - padding;
      r->y1 = r->y1 - padding;
      r->x2 = r->x2 + padding;
      r->y2 = r->y2 + padding;
      currentOverlaps = false;
      for(j = 0.0; j < nextRectangle->numberValue; j = j + 1.0){
        currentOverlaps = currentOverlaps || RectanglesOverlap(r, occupied->at(j));
      }
      /* Draw labels with priority 1 if they do not overlap anything else. */
      if( !currentOverlaps  && p == 1.0){
        DrawText(canvas, r->x1 + padding, r->y1 + padding, text, gridLabelColor);
        CopyRectangleValues(occupied->at(nextRectangle->numberValue), r);
        nextRectangle->numberValue = nextRectangle->numberValue + 1.0;
      }
      overlap = overlap || currentOverlaps;
    }
  }
  if( !overlap  && p != 1.0){
    for(i = 0.0; i < yGridPositions->size(); i = i + 1.0){
      y = yGridPositions->at(i);
      py = MapYCoordinate(y, yMin, yMax, yPixelMin, yPixelMax);
      if(yLabelPriorities->numberArray->at(i) == p){
        text = yLabels->stringArray->at(i)->string;
        if(textOnLeft){
          r->x1 = floor(ox - GetTextWidth(text) - 10.0);
        }else{
          r->x1 = floor(ox + 10.0);
        }
        r->y1 = floor(py - 6.0);
        r->x2 = r->x1 + GetTextWidth(text);
        r->y2 = r->y1 + GetTextHeight(text);
        DrawText(canvas, r->x1, r->y1, text, gridLabelColor);
        CopyRectangleValues(occupied->at(nextRectangle->numberValue), r);
        nextRectangle->numberValue = nextRectangle->numberValue + 1.0;
      }
    }
  }
}
vector *ComputeGridLinePositions(double cMin, double cMax, StringArrayReference *labels, NumberArrayReference *priorities){
  vector *positions;
  double cLength, p, pMin, pMax, pInterval, pNum, i, num, rem, priority, mode;
  cLength = cMax - cMin;
  p = floor(log10(cLength));
  pInterval = pow(10.0, p);
  /* gives 10-1 lines for 100-10 diff */
  pMin = ceil(cMin/pInterval)*pInterval;
  pMax = floor(cMax/pInterval)*pInterval;
  pNum = Round((pMax - pMin)/pInterval + 1.0);
  mode = 1.0;
  if(pNum <= 3.0){
    p = floor(log10(cLength) - 1.0);
    /* gives 100-10 lines for 100-10 diff */
    pInterval = pow(10.0, p);
    pMin = ceil(cMin/pInterval)*pInterval;
    pMax = floor(cMax/pInterval)*pInterval;
    pNum = Round((pMax - pMin)/pInterval + 1.0);
    mode = 4.0;
  }else if(pNum <= 6.0){
    p = floor(log10(cLength));
    pInterval = pow(10.0, p)/4.0;
    /* gives 40-5 lines for 100-10 diff */
    pMin = ceil(cMin/pInterval)*pInterval;
    pMax = floor(cMax/pInterval)*pInterval;
    pNum = Round((pMax - pMin)/pInterval + 1.0);
    mode = 3.0;
  }else if(pNum <= 10.0){
    p = floor(log10(cLength));
    pInterval = pow(10.0, p)/2.0;
    /* gives 20-3 lines for 100-10 diff */
    pMin = ceil(cMin/pInterval)*pInterval;
    pMax = floor(cMax/pInterval)*pInterval;
    pNum = Round((pMax - pMin)/pInterval + 1.0);
    mode = 2.0;
  }
  positions = new vector (pNum);
  labels->stringArray = new vector (pNum);
  priorities->numberArray = new vector (pNum);
  for(i = 0.0; i < pNum; i = i + 1.0){
    num = pMin + pInterval*i;
    positions->at(i) = num;
    /* Always print priority 1 labels. Only draw priority 2 if they can all be drawn. Then, only draw priority 3 if they can all be drawn. */
    priority = 1.0;
    /* Prioritize x.25, x.5 and x.75 lower. */
    if(mode == 2.0 || mode == 3.0){
      rem = fmod(abs(round(num/pow(10.0, p - 2.0))), 100.0);
      priority = 1.0;
      if(rem == 50.0){
        priority = 2.0;
      }else if(rem == 25.0 || rem == 75.0){
        priority = 3.0;
      }
    }
    /* Prioritize x.1-x.4 and x.6-x.9 lower */
    if(mode == 4.0){
      rem = fmod(abs(Round(num/pow(10.0, p))), 10.0);
      priority = 1.0;
      if(rem == 1.0 || rem == 2.0 || rem == 3.0 || rem == 4.0 || rem == 6.0 || rem == 7.0 || rem == 8.0 || rem == 9.0){
        priority = 2.0;
      }
    }
    /* 0 has lowest priority. */
    if(EpsilonCompare(num, 0.0, pow(10.0, p - 5.0))){
      priority = 3.0;
    }
    priorities->numberArray->at(i) = priority;
    /* The label itself. */
    labels->stringArray->at(i) = new StringReference();
    if(p < 0.0){
      if(mode == 2.0 || mode == 3.0){
        num = RoundToDigits(num,  -(p - 1.0));
      }else{
        num = RoundToDigits(num,  -p);
      }
    }
    labels->stringArray->at(i)->string = CreateStringDecimalFromNumber(num);
  }
  return positions;
}
double MapYCoordinate(double y, double yMin, double yMax, double yPixelMin, double yPixelMax){
  double yLength, yPixelLength;
  yLength = yMax - yMin;
  yPixelLength = yPixelMax - yPixelMin;
  y = y - yMin;
  y = y*yPixelLength/yLength;
  y = yPixelLength - y;
  y = y + yPixelMin;
  return y;
}
double MapXCoordinate(double x, double xMin, double xMax, double xPixelMin, double xPixelMax){
  double xLength, xPixelLength;
  xLength = xMax - xMin;
  xPixelLength = xPixelMax - xPixelMin;
  x = x - xMin;
  x = x*xPixelLength/xLength;
  x = x + xPixelMin;
  return x;
}
double MapXCoordinateAutoSettings(double x, RGBABitmapImage *image, vector *xs){
  return MapXCoordinate(x, GetMinimum(xs), GetMaximum(xs), GetDefaultPaddingPercentage()*ImageWidth(image), (1.0 - GetDefaultPaddingPercentage())*ImageWidth(image));
}
double MapYCoordinateAutoSettings(double y, RGBABitmapImage *image, vector *ys){
  return MapYCoordinate(y, GetMinimum(ys), GetMaximum(ys), GetDefaultPaddingPercentage()*ImageHeight(image), (1.0 - GetDefaultPaddingPercentage())*ImageHeight(image));
}
double MapXCoordinateBasedOnSettings(double x, ScatterPlotSettings *settings){
  double xMin, xMax, xPadding, xPixelMin, xPixelMax;
  Rectangle *boundaries;
  boundaries = new Rectangle();
  ComputeBoundariesBasedOnSettings(settings, boundaries);
  xMin = boundaries->x1;
  xMax = boundaries->x2;
  if(settings->autoPadding){
    xPadding = floor(GetDefaultPaddingPercentage()*settings->width);
  }else{
    xPadding = settings->xPadding;
  }
  xPixelMin = xPadding;
  xPixelMax = settings->width - xPadding;
  return MapXCoordinate(x, xMin, xMax, xPixelMin, xPixelMax);
}
double MapYCoordinateBasedOnSettings(double y, ScatterPlotSettings *settings){
  double yMin, yMax, yPadding, yPixelMin, yPixelMax;
  Rectangle *boundaries;
  boundaries = new Rectangle();
  ComputeBoundariesBasedOnSettings(settings, boundaries);
  yMin = boundaries->y1;
  yMax = boundaries->y2;
  if(settings->autoPadding){
    yPadding = floor(GetDefaultPaddingPercentage()*settings->height);
  }else{
    yPadding = settings->yPadding;
  }
  yPixelMin = yPadding;
  yPixelMax = settings->height - yPadding;
  return MapYCoordinate(y, yMin, yMax, yPixelMin, yPixelMax);
}
double GetDefaultPaddingPercentage(){
  return 0.10;
}
void DrawText(RGBABitmapImage *canvas, double x, double y, vector *text, RGBA *color){
  double i, charWidth, spacing;
  charWidth = 8.0;
  spacing = 2.0;
  for(i = 0.0; i < text->size(); i = i + 1.0){
    DrawAsciiCharacter(canvas, x + i*(charWidth + spacing), y, text->at(i), color);
  }
}
void DrawTextUpwards(RGBABitmapImage *canvas, double x, double y, vector *text, RGBA *color){
  RGBABitmapImage *buffer, *rotated;
  buffer = CreateImage(GetTextWidth(text), GetTextHeight(text), GetTransparent());
  DrawText(buffer, 0.0, 0.0, text, color);
  rotated = RotateAntiClockwise90Degrees(buffer);
  DrawImageOnImage(canvas, rotated, x, y);
  DeleteImage(buffer);
  DeleteImage(rotated);
}
ScatterPlotSettings *GetDefaultScatterPlotSettings(){
  ScatterPlotSettings *settings;
  settings = new ScatterPlotSettings();
  settings->autoBoundaries = true;
  settings->xMax = 0.0;
  settings->xMin = 0.0;
  settings->yMax = 0.0;
  settings->yMin = 0.0;
  settings->autoPadding = true;
  settings->xPadding = 0.0;
  settings->yPadding = 0.0;
  settings->title = toVector(L"");
  settings->xLabel = toVector(L"");
  settings->yLabel = toVector(L"");
  settings->scatterPlotSeries = new vector (0.0);
  settings->showGrid = true;
  settings->gridColor = GetGray(0.1);
  settings->xAxisAuto = true;
  settings->xAxisTop = false;
  settings->xAxisBottom = false;
  settings->yAxisAuto = true;
  settings->yAxisLeft = false;
  settings->yAxisRight = false;
  return settings;
}
ScatterPlotSeries *GetDefaultScatterPlotSeriesSettings(){
  ScatterPlotSeries *series;
  series = new ScatterPlotSeries();
  series->linearInterpolation = true;
  series->pointType = toVector(L"pixels");
  series->lineType = toVector(L"solid");
  series->lineThickness = 1.0;
  series->xs = new vector (0.0);
  series->ys = new vector (0.0);
  series->color = GetBlack();
  return series;
}
void DrawScatterPlot(RGBABitmapImageReference *canvasReference, double width, double height, vector *xs, vector *ys){
  ScatterPlotSettings *settings;
  settings = GetDefaultScatterPlotSettings();
  settings->width = width;
  settings->height = height;
  settings->scatterPlotSeries = new vector (1.0);
  settings->scatterPlotSeries->at(0) = GetDefaultScatterPlotSeriesSettings();
  delete settings->scatterPlotSeries->at(0)->xs;
  settings->scatterPlotSeries->at(0)->xs = xs;
  delete settings->scatterPlotSeries->at(0)->ys;
  settings->scatterPlotSeries->at(0)->ys = ys;
  DrawScatterPlotFromSettings(canvasReference, settings);
}
bool DrawScatterPlotFromSettings(RGBABitmapImageReference *canvasReference, ScatterPlotSettings *settings){
  double xMin, xMax, yMin, yMax, xLength, yLength, i, x, y, xPrev, yPrev, px, py, pxPrev, pyPrev, originX, originY, p, l, plot;
  Rectangle *boundaries;
  double xPadding, yPadding, originXPixels, originYPixels;
  double xPixelMin, yPixelMin, xPixelMax, yPixelMax, xLengthPixels, yLengthPixels, axisLabelPadding;
  NumberReference *nextRectangle, *x1Ref, *y1Ref, *x2Ref, *y2Ref, *patternOffset;
  bool prevSet, success;
  RGBA *gridLabelColor;
  RGBABitmapImage *canvas;
  vector *xs, *ys;
  bool linearInterpolation;
  ScatterPlotSeries *sp;
  vector *xGridPositions, *yGridPositions;
  StringArrayReference *xLabels, *yLabels;
  NumberArrayReference *xLabelPriorities, *yLabelPriorities;
  vector *occupied;
  vector *linePattern;
  bool originXInside, originYInside, textOnLeft, textOnBottom;
  double originTextX, originTextY, originTextXPixels, originTextYPixels, side;
  canvas = CreateImage(settings->width, settings->height, GetWhite());
  patternOffset = CreateNumberReference(0.0);
  success = ScatterPlotFromSettingsValid(settings);
  if(success){
    boundaries = new Rectangle();
    ComputeBoundariesBasedOnSettings(settings, boundaries);
    xMin = boundaries->x1;
    yMin = boundaries->y1;
    xMax = boundaries->x2;
    yMax = boundaries->y2;
    // If zero, set to defaults.
    if(xMin - xMax == 0){
        xMin = 0;
        xMax = 10;
    }
    if(yMin - yMax == 0){
        yMin = 0;
        yMax = 10;
    }
    xLength = xMax - xMin;
    yLength = yMax - yMin;
    if(settings->autoPadding){
      xPadding = floor(GetDefaultPaddingPercentage()*settings->width);
      yPadding = floor(GetDefaultPaddingPercentage()*settings->height);
    }else{
      xPadding = settings->xPadding;
      yPadding = settings->yPadding;
    }
    /* Draw title */
    DrawText(canvas, floor(settings->width/2.0 - GetTextWidth(settings->title)/2.0), floor(yPadding/3.0), settings->title, GetBlack());
    /* Draw grid */
    xPixelMin = xPadding;
    yPixelMin = yPadding;
    xPixelMax = settings->width - xPadding;
    yPixelMax = settings->height - yPadding;
    xLengthPixels = xPixelMax - xPixelMin;
    yLengthPixels = yPixelMax - yPixelMin;
    DrawRectangle1px(canvas, xPixelMin, yPixelMin, xLengthPixels, yLengthPixels, settings->gridColor);
    gridLabelColor = GetGray(0.5);
    xLabels = new StringArrayReference();
    xLabelPriorities = new NumberArrayReference();
    yLabels = new StringArrayReference();
    yLabelPriorities = new NumberArrayReference();
    xGridPositions = ComputeGridLinePositions(xMin, xMax, xLabels, xLabelPriorities);
    yGridPositions = ComputeGridLinePositions(yMin, yMax, yLabels, yLabelPriorities);
    if(settings->showGrid){
      /* X-grid */
      for(i = 0.0; i < xGridPositions->size(); i = i + 1.0){
        x = xGridPositions->at(i);
        px = MapXCoordinate(x, xMin, xMax, xPixelMin, xPixelMax);
        DrawLine1px(canvas, px, yPixelMin, px, yPixelMax, settings->gridColor);
      }
      /* Y-grid */
      for(i = 0.0; i < yGridPositions->size(); i = i + 1.0){
        y = yGridPositions->at(i);
        py = MapYCoordinate(y, yMin, yMax, yPixelMin, yPixelMax);
        DrawLine1px(canvas, xPixelMin, py, xPixelMax, py, settings->gridColor);
      }
    }
    /* Compute origin information. */
    originYInside = yMin < 0.0 && yMax > 0.0;
    originY = 0.0;
    if(settings->xAxisAuto){
      if(originYInside){
        originY = 0.0;
      }else{
        originY = yMin;
      }
    }else{
if(settings->xAxisTop){
        originY = yMax;
      }
      if(settings->xAxisBottom){
        originY = yMin;
      }
    }
    originYPixels = MapYCoordinate(originY, yMin, yMax, yPixelMin, yPixelMax);
    originXInside = xMin < 0.0 && xMax > 0.0;
    originX = 0.0;
    if(settings->yAxisAuto){
      if(originXInside){
        originX = 0.0;
      }else{
        originX = xMin;
      }
    }else{
if(settings->yAxisLeft){
        originX = xMin;
      }
      if(settings->yAxisRight){
        originX = xMax;
      }
    }
    originXPixels = MapXCoordinate(originX, xMin, xMax, xPixelMin, xPixelMax);
    if(originYInside){
      originTextY = 0.0;
    }else{
      originTextY = yMin + yLength/2.0;
    }
    originTextYPixels = MapYCoordinate(originTextY, yMin, yMax, yPixelMin, yPixelMax);
    if(originXInside){
      originTextX = 0.0;
    }else{
      originTextX = xMin + xLength/2.0;
    }
    originTextXPixels = MapXCoordinate(originTextX, xMin, xMax, xPixelMin, xPixelMax);
    /* Labels */
    occupied = new vector (xLabels->stringArray->size() + yLabels->stringArray->size());
    for(i = 0.0; i < occupied->size(); i = i + 1.0){
      occupied->at(i) = CreateRectangle(0.0, 0.0, 0.0, 0.0);
    }
    nextRectangle = CreateNumberReference(0.0);
    /* x labels */
    for(i = 1.0; i <= 5.0; i = i + 1.0){
      textOnBottom = true;
      if( !settings->xAxisAuto  && settings->xAxisTop){
        textOnBottom = false;
      }
      DrawXLabelsForPriority(i, xMin, originYPixels, xMax, xPixelMin, xPixelMax, nextRectangle, gridLabelColor, canvas, xGridPositions, xLabels, xLabelPriorities, occupied, textOnBottom);
    }
    /* y labels */
    for(i = 1.0; i <= 5.0; i = i + 1.0){
      textOnLeft = true;
      if( !settings->yAxisAuto  && settings->yAxisRight){
        textOnLeft = false;
      }
      DrawYLabelsForPriority(i, yMin, originXPixels, yMax, yPixelMin, yPixelMax, nextRectangle, gridLabelColor, canvas, yGridPositions, yLabels, yLabelPriorities, occupied, textOnLeft);
    }
    /* Draw origin line axis titles. */
    axisLabelPadding = 20.0;
    /* x origin line */
    if(originYInside){
      DrawLine1px(canvas, Round(xPixelMin), Round(originYPixels), Round(xPixelMax), Round(originYPixels), GetBlack());
    }
    /* y origin line */
    if(originXInside){
      DrawLine1px(canvas, Round(originXPixels), Round(yPixelMin), Round(originXPixels), Round(yPixelMax), GetBlack());
    }
    /* Draw origin axis titles. */
    DrawTextUpwards(canvas, 10.0, floor(originTextYPixels - GetTextWidth(settings->yLabel)/2.0), settings->yLabel, GetBlack());
    DrawText(canvas, floor(originTextXPixels - GetTextWidth(settings->xLabel)/2.0), yPixelMax + axisLabelPadding, settings->xLabel, GetBlack());
    /* X-grid-markers */
    for(i = 0.0; i < xGridPositions->size(); i = i + 1.0){
      x = xGridPositions->at(i);
      px = MapXCoordinate(x, xMin, xMax, xPixelMin, xPixelMax);
      p = xLabelPriorities->numberArray->at(i);
      l = 1.0;
      if(p == 1.0){
        l = 8.0;
      }else if(p == 2.0){
        l = 3.0;
      }
      side =  -1.0;
      if( !settings->xAxisAuto  && settings->xAxisTop){
        side = 1.0;
      }
      DrawLine1px(canvas, px, originYPixels, px, originYPixels + side*l, GetBlack());
    }
    /* Y-grid-markers */
    for(i = 0.0; i < yGridPositions->size(); i = i + 1.0){
      y = yGridPositions->at(i);
      py = MapYCoordinate(y, yMin, yMax, yPixelMin, yPixelMax);
      p = yLabelPriorities->numberArray->at(i);
      l = 1.0;
      if(p == 1.0){
        l = 8.0;
      }else if(p == 2.0){
        l = 3.0;
      }
      side = 1.0;
      if( !settings->yAxisAuto  && settings->yAxisRight){
        side =  -1.0;
      }
      DrawLine1px(canvas, originXPixels, py, originXPixels + side*l, py, GetBlack());
    }
    /* Draw points */
    for(plot = 0.0; plot < settings->scatterPlotSeries->size(); plot = plot + 1.0){
      sp = settings->scatterPlotSeries->at(plot);
      xs = sp->xs;
      ys = sp->ys;
      linearInterpolation = sp->linearInterpolation;
      x1Ref = new NumberReference();
      y1Ref = new NumberReference();
      x2Ref = new NumberReference();
      y2Ref = new NumberReference();
      if(linearInterpolation){
        prevSet = false;
        xPrev = 0.0;
        yPrev = 0.0;
        for(i = 0.0; i < xs->size(); i = i + 1.0){
          x = xs->at(i);
          y = ys->at(i);
          if(prevSet){
            x1Ref->numberValue = xPrev;
            y1Ref->numberValue = yPrev;
            x2Ref->numberValue = x;
            y2Ref->numberValue = y;
            success = CropLineWithinBoundary(x1Ref, y1Ref, x2Ref, y2Ref, xMin, xMax, yMin, yMax);
            if(success){
              pxPrev = floor(MapXCoordinate(x1Ref->numberValue, xMin, xMax, xPixelMin, xPixelMax));
              pyPrev = floor(MapYCoordinate(y1Ref->numberValue, yMin, yMax, yPixelMin, yPixelMax));
              px = floor(MapXCoordinate(x2Ref->numberValue, xMin, xMax, xPixelMin, xPixelMax));
              py = floor(MapYCoordinate(y2Ref->numberValue, yMin, yMax, yPixelMin, yPixelMax));
              if(aStringsEqual(sp->lineType, toVector(L"solid")) && sp->lineThickness == 1.0){
                DrawLine1px(canvas, pxPrev, pyPrev, px, py, sp->color);
              }else if(aStringsEqual(sp->lineType, toVector(L"solid"))){
                DrawLine(canvas, pxPrev, pyPrev, px, py, sp->lineThickness, sp->color);
              }else if(aStringsEqual(sp->lineType, toVector(L"dashed"))){
                linePattern = GetLinePattern1();
                DrawLineBresenhamsAlgorithmThickPatterned(canvas, pxPrev, pyPrev, px, py, sp->lineThickness, linePattern, patternOffset, sp->color);
              }else if(aStringsEqual(sp->lineType, toVector(L"dotted"))){
                linePattern = GetLinePattern2();
                DrawLineBresenhamsAlgorithmThickPatterned(canvas, pxPrev, pyPrev, px, py, sp->lineThickness, linePattern, patternOffset, sp->color);
              }else if(aStringsEqual(sp->lineType, toVector(L"dotdash"))){
                linePattern = GetLinePattern3();
                DrawLineBresenhamsAlgorithmThickPatterned(canvas, pxPrev, pyPrev, px, py, sp->lineThickness, linePattern, patternOffset, sp->color);
              }else if(aStringsEqual(sp->lineType, toVector(L"longdash"))){
                linePattern = GetLinePattern4();
                DrawLineBresenhamsAlgorithmThickPatterned(canvas, pxPrev, pyPrev, px, py, sp->lineThickness, linePattern, patternOffset, sp->color);
              }else if(aStringsEqual(sp->lineType, toVector(L"twodash"))){
                linePattern = GetLinePattern5();
                DrawLineBresenhamsAlgorithmThickPatterned(canvas, pxPrev, pyPrev, px, py, sp->lineThickness, linePattern, patternOffset, sp->color);
              }
            }
          }
          prevSet = true;
          xPrev = x;
          yPrev = y;
        }
      }else{
        for(i = 0.0; i < xs->size(); i = i + 1.0){
          x = xs->at(i);
          y = ys->at(i);
          if(x > xMin && x < xMax && y > yMin && y < yMax){
            x = floor(MapXCoordinate(x, xMin, xMax, xPixelMin, xPixelMax));
            y = floor(MapYCoordinate(y, yMin, yMax, yPixelMin, yPixelMax));
            if(aStringsEqual(sp->pointType, toVector(L"crosses"))){
              DrawPixel(canvas, x, y, sp->color);
              DrawPixel(canvas, x + 1.0, y, sp->color);
              DrawPixel(canvas, x + 2.0, y, sp->color);
              DrawPixel(canvas, x - 1.0, y, sp->color);
              DrawPixel(canvas, x - 2.0, y, sp->color);
              DrawPixel(canvas, x, y + 1.0, sp->color);
              DrawPixel(canvas, x, y + 2.0, sp->color);
              DrawPixel(canvas, x, y - 1.0, sp->color);
              DrawPixel(canvas, x, y - 2.0, sp->color);
            }else if(aStringsEqual(sp->pointType, toVector(L"circles"))){
              DrawCircle(canvas, x, y, 3.0, sp->color);
            }else if(aStringsEqual(sp->pointType, toVector(L"dots"))){
              DrawFilledCircle(canvas, x, y, 3.0, sp->color);
            }else if(aStringsEqual(sp->pointType, toVector(L"triangles"))){
              DrawTriangle(canvas, x, y, 3.0, sp->color);
            }else if(aStringsEqual(sp->pointType, toVector(L"filled triangles"))){
              DrawFilledTriangle(canvas, x, y, 3.0, sp->color);
            }else if(aStringsEqual(sp->pointType, toVector(L"pixels"))){
              DrawPixel(canvas, x, y, sp->color);
            }
          }
        }
      }
    }
    DeleteImage(canvasReference->image);
    canvasReference->image = canvas;
  }
  return success;
}
void ComputeBoundariesBasedOnSettings(ScatterPlotSettings *settings, Rectangle *boundaries){
  ScatterPlotSeries *sp;
  double plot, xMin, xMax, yMin, yMax;
  if(settings->scatterPlotSeries->size() >= 1.0){
    xMin = GetMinimum(settings->scatterPlotSeries->at(0)->xs);
    xMax = GetMaximum(settings->scatterPlotSeries->at(0)->xs);
    yMin = GetMinimum(settings->scatterPlotSeries->at(0)->ys);
    yMax = GetMaximum(settings->scatterPlotSeries->at(0)->ys);
  }else{
    xMin =  -10.0;
    xMax = 10.0;
    yMin =  -10.0;
    yMax = 10.0;
  }
  if( !settings->autoBoundaries ){
    xMin = settings->xMin;
    xMax = settings->xMax;
    yMin = settings->yMin;
    yMax = settings->yMax;
  }else{
    for(plot = 1.0; plot < settings->scatterPlotSeries->size(); plot = plot + 1.0){
      sp = settings->scatterPlotSeries->at(plot);
      xMin = fmin(xMin, GetMinimum(sp->xs));
      xMax = fmax(xMax, GetMaximum(sp->xs));
      yMin = fmin(yMin, GetMinimum(sp->ys));
      yMax = fmax(yMax, GetMaximum(sp->ys));
    }
  }
  boundaries->x1 = xMin;
  boundaries->y1 = yMin;
  boundaries->x2 = xMax;
  boundaries->y2 = yMax;
}
bool ScatterPlotFromSettingsValid(ScatterPlotSettings *settings){
  bool success, found;
  ScatterPlotSeries *series;
  double i;
  success = true;
  /* Check axis placement. */
  if( !settings->xAxisAuto ){
    if(settings->xAxisTop && settings->xAxisBottom){
      success = false;
    }
    if( !settings->xAxisTop  &&  !settings->xAxisBottom ){
      success = false;
    }
  }
  if( !settings->yAxisAuto ){
    if(settings->yAxisLeft && settings->yAxisRight){
      success = false;
    }
    if( !settings->yAxisLeft  &&  !settings->yAxisRight ){
      success = false;
    }
  }
  /* Check series lengths. */
  for(i = 0.0; i < settings->scatterPlotSeries->size(); i = i + 1.0){
    series = settings->scatterPlotSeries->at(i);
    if(series->xs->size() != series->ys->size()){
      success = false;
    }
    if(series->xs->size() == 0.0){
      success = false;
    }
    if(series->linearInterpolation && series->xs->size() == 1.0){
      success = false;
    }
  }
  /* Check bounds. */
  if( !settings->autoBoundaries ){
    if(settings->xMin >= settings->xMax){
      success = false;
    }
    if(settings->yMin >= settings->yMax){
      success = false;
    }
  }
  /* Check padding. */
  if( !settings->autoPadding ){
    if(2.0*settings->xPadding >= settings->width){
      success = false;
    }
    if(2.0*settings->yPadding >= settings->height){
      success = false;
    }
  }
  /* Check width and height. */
  if(settings->width < 0.0){
    success = false;
  }
  if(settings->height < 0.0){
    success = false;
  }
  /* Check point types. */
  for(i = 0.0; i < settings->scatterPlotSeries->size(); i = i + 1.0){
    series = settings->scatterPlotSeries->at(i);
    if(series->lineThickness < 0.0){
      success = false;
    }
    if( !series->linearInterpolation ){
      /* Point type. */
      found = false;
      if(aStringsEqual(series->pointType, toVector(L"crosses"))){
        found = true;
      }else if(aStringsEqual(series->pointType, toVector(L"circles"))){
        found = true;
      }else if(aStringsEqual(series->pointType, toVector(L"dots"))){
        found = true;
      }else if(aStringsEqual(series->pointType, toVector(L"triangles"))){
        found = true;
      }else if(aStringsEqual(series->pointType, toVector(L"filled triangles"))){
        found = true;
      }else if(aStringsEqual(series->pointType, toVector(L"pixels"))){
        found = true;
      }
      if( !found ){
        success = false;
      }
    }else{
      /* Line type. */
      found = false;
      if(aStringsEqual(series->lineType, toVector(L"solid"))){
        found = true;
      }else if(aStringsEqual(series->lineType, toVector(L"dashed"))){
        found = true;
      }else if(aStringsEqual(series->lineType, toVector(L"dotted"))){
        found = true;
      }else if(aStringsEqual(series->lineType, toVector(L"dotdash"))){
        found = true;
      }else if(aStringsEqual(series->lineType, toVector(L"longdash"))){
        found = true;
      }else if(aStringsEqual(series->lineType, toVector(L"twodash"))){
        found = true;
      }
      if( !found ){
        success = false;
      }
    }
  }
  return success;
}
BarPlotSettings *GetDefaultBarPlotSettings(){
  BarPlotSettings *settings;
  settings = new BarPlotSettings();
  settings->width = 800.0;
  settings->height = 600.0;
  settings->autoBoundaries = true;
  settings->yMax = 0.0;
  settings->yMin = 0.0;
  settings->autoPadding = true;
  settings->xPadding = 0.0;
  settings->yPadding = 0.0;
  settings->title = toVector(L"");
  settings->yLabel = toVector(L"");
  settings->barPlotSeries = new vector (0.0);
  settings->showGrid = true;
  settings->gridColor = GetGray(0.1);
  settings->autoColor = true;
  settings->grayscaleAutoColor = false;
  settings->autoSpacing = true;
  settings->groupSeparation = 0.0;
  settings->barSeparation = 0.0;
  settings->autoLabels = true;
  settings->xLabels = new vector (0.0);
  /*settings.autoLabels = false;
        settings.xLabels = new StringReference [5];
        settings.xLabels[0] = CreateStringReference("may 20".toCharArray());
        settings.xLabels[1] = CreateStringReference("jun 20".toCharArray());
        settings.xLabels[2] = CreateStringReference("jul 20".toCharArray());
        settings.xLabels[3] = CreateStringReference("aug 20".toCharArray());
        settings.xLabels[4] = CreateStringReference("sep 20".toCharArray()); */
  settings->barBorder = false;
  return settings;
}
BarPlotSeries *GetDefaultBarPlotSeriesSettings(){
  BarPlotSeries *series;
  series = new BarPlotSeries();
  series->ys = new vector (0.0);
  series->color = GetBlack();
  return series;
}
RGBABitmapImage *DrawBarPlot(double width, double height, vector *ys){
  BarPlotSettings *settings;
  RGBABitmapImageReference *canvasReference;
  settings = GetDefaultBarPlotSettings();
  settings->barPlotSeries = new vector (1.0);
  settings->barPlotSeries->at(0) = GetDefaultBarPlotSeriesSettings();
  delete settings->barPlotSeries->at(0)->ys;
  settings->barPlotSeries->at(0)->ys = ys;
  canvasReference = new RGBABitmapImageReference();
  settings->width = width;
  settings->height = height;
  DrawBarPlotFromSettings(canvasReference, settings);
  return canvasReference->image;
}
bool DrawBarPlotFromSettings(RGBABitmapImageReference *canvasReference, BarPlotSettings *settings){
  double xPadding, yPadding;
  double xPixelMin, yPixelMin, yPixelMax, xPixelMax;
  double xLengthPixels, yLengthPixels;
  double s, n, y, x, w, h, yMin, yMax, b, i, py, yValue;
  vector *colors;
  vector *ys, *yGridPositions;
  double yTop, yBottom, ss, bs, yLength;
  double groupSeparation, barSeparation, barWidth, textwidth;
  StringArrayReference *yLabels;
  NumberArrayReference *yLabelPriorities;
  vector *occupied;
  NumberReference *nextRectangle;
  RGBA *gridLabelColor, *barColor;
  vector *label;
  bool success;
  RGBABitmapImage *canvas;
  success = BarPlotSettingsIsValid(settings);
  if(success){
    canvas = CreateImage(settings->width, settings->height, GetWhite());
    ss = settings->barPlotSeries->size();
    gridLabelColor = GetGray(0.5);
    /* padding */
    if(settings->autoPadding){
      xPadding = floor(GetDefaultPaddingPercentage()*ImageWidth(canvas));
      yPadding = floor(GetDefaultPaddingPercentage()*ImageHeight(canvas));
    }else{
      xPadding = settings->xPadding;
      yPadding = settings->yPadding;
    }
    /* Draw title */
    DrawText(canvas, floor(ImageWidth(canvas)/2.0 - GetTextWidth(settings->title)/2.0), floor(yPadding/3.0), settings->title, GetBlack());
    DrawTextUpwards(canvas, 10.0, floor(ImageHeight(canvas)/2.0 - GetTextWidth(settings->yLabel)/2.0), settings->yLabel, GetBlack());
    /* min and max */
    if(settings->autoBoundaries){
      if(ss >= 1.0){
        yMax = GetMaximum(settings->barPlotSeries->at(0)->ys);
        yMin = fmin(0.0, GetMinimum(settings->barPlotSeries->at(0)->ys));
        for(s = 0.0; s < ss; s = s + 1.0){
          yMax = fmax(yMax, GetMaximum(settings->barPlotSeries->at(s)->ys));
          yMin = fmin(yMin, GetMinimum(settings->barPlotSeries->at(s)->ys));
        }
      }else{
        yMax = 10.0;
        yMin = 0.0;
      }
    }else{
      yMin = settings->yMin;
      yMax = settings->yMax;
    }
    yLength = yMax - yMin;
    /* boundaries */
    xPixelMin = xPadding;
    yPixelMin = yPadding;
    xPixelMax = ImageWidth(canvas) - xPadding;
    yPixelMax = ImageHeight(canvas) - yPadding;
    xLengthPixels = xPixelMax - xPixelMin;
    yLengthPixels = yPixelMax - yPixelMin;
    /* Draw boundary. */
    DrawRectangle1px(canvas, xPixelMin, yPixelMin, xLengthPixels, yLengthPixels, settings->gridColor);
    /* Draw grid lines. */
    yLabels = new StringArrayReference();
    yLabelPriorities = new NumberArrayReference();
    yGridPositions = ComputeGridLinePositions(yMin, yMax, yLabels, yLabelPriorities);
    if(settings->showGrid){
      /* Y-grid */
      for(i = 0.0; i < yGridPositions->size(); i = i + 1.0){
        y = yGridPositions->at(i);
        py = MapYCoordinate(y, yMin, yMax, yPixelMin, yPixelMax);
        DrawLine1px(canvas, xPixelMin, py, xPixelMax, py, settings->gridColor);
      }
    }
    /* Draw origin. */
    if(yMin < 0.0 && yMax > 0.0){
      py = MapYCoordinate(0.0, yMin, yMax, yPixelMin, yPixelMax);
      DrawLine1px(canvas, xPixelMin, py, xPixelMax, py, settings->gridColor);
    }
    /* Labels */
    occupied = new vector (yLabels->stringArray->size());
    for(i = 0.0; i < occupied->size(); i = i + 1.0){
      occupied->at(i) = CreateRectangle(0.0, 0.0, 0.0, 0.0);
    }
    nextRectangle = CreateNumberReference(0.0);
    for(i = 1.0; i <= 5.0; i = i + 1.0){
      DrawYLabelsForPriority(i, yMin, xPixelMin, yMax, yPixelMin, yPixelMax, nextRectangle, gridLabelColor, canvas, yGridPositions, yLabels, yLabelPriorities, occupied, true);
    }
    /* Draw bars. */
    if(settings->autoColor){
      if( !settings->grayscaleAutoColor ){
        colors = Get8HighContrastColors();
      }else{
        colors = new vector (ss);
        if(ss > 1.0){
          for(i = 0.0; i < ss; i = i + 1.0){
            colors->at(i) = GetGray(0.7 - (i/ss)*0.7);
          }
        }else{
          colors->at(0) = GetGray(0.5);
        }
      }
    }else{
      colors = new vector (0.0);
    }
    /* distances */
    bs = settings->barPlotSeries->at(0)->ys->size();
    if(settings->autoSpacing){
      groupSeparation = ImageWidth(canvas)*0.05;
      barSeparation = ImageWidth(canvas)*0.005;
    }else{
      groupSeparation = settings->groupSeparation;
      barSeparation = settings->barSeparation;
    }
    barWidth = (xLengthPixels - groupSeparation*(bs - 1.0) - barSeparation*(bs*(ss - 1.0)))/(bs*ss);
    /* Draw bars. */
    b = 0.0;
    for(n = 0.0; n < bs; n = n + 1.0){
      for(s = 0.0; s < ss; s = s + 1.0){
        ys = settings->barPlotSeries->at(s)->ys;
        yValue = ys->at(n);
        yBottom = MapYCoordinate(yValue, yMin, yMax, yPixelMin, yPixelMax);
        yTop = MapYCoordinate(0.0, yMin, yMax, yPixelMin, yPixelMax);
        x = xPixelMin + n*(groupSeparation + ss*barWidth) + s*(barWidth) + b*barSeparation;
        w = barWidth;
        if(yValue >= 0.0){
          y = yBottom;
          h = yTop - y;
        }else{
          y = yTop;
          h = yBottom - yTop;
        }
        /* Cut at boundaries. */
        if(y < yPixelMin && y + h > yPixelMax){
          y = yPixelMin;
          h = yPixelMax - yPixelMin;
        }else if(y < yPixelMin){
          y = yPixelMin;
          if(yValue >= 0.0){
            h = yTop - y;
          }else{
            h = yBottom - y;
          }
        }else if(y + h > yPixelMax){
          h = yPixelMax - y;
        }
        /* Get color */
        if(settings->autoColor){
          barColor = colors->at(s);
        }else{
          barColor = settings->barPlotSeries->at(s)->color;
        }
        /* Draw */
        if(settings->barBorder){
          DrawFilledRectangleWithBorder(canvas, Round(x), Round(y), Round(w), Round(h), GetBlack(), barColor);
        }else{
          DrawFilledRectangle(canvas, Round(x), Round(y), Round(w), Round(h), barColor);
        }
        b = b + 1.0;
      }
      b = b - 1.0;
    }
    /* x-labels */
    for(n = 0.0; n < bs; n = n + 1.0){
      if(settings->autoLabels){
        label = CreateStringDecimalFromNumber(n + 1.0);
      }else{
        label = settings->xLabels->at(n)->string;
      }
      textwidth = GetTextWidth(label);
      x = xPixelMin + (n + 0.5)*(ss*barWidth + (ss - 1.0)*barSeparation) + n*groupSeparation - textwidth/2.0;
      DrawText(canvas, floor(x), ImageHeight(canvas) - yPadding + 20.0, label, gridLabelColor);
      b = b + 1.0;
    }
    canvasReference->image = canvas;
  }
  return success;
}
bool BarPlotSettingsIsValid(BarPlotSettings *settings){
  bool success, lengthSet;
  BarPlotSeries *series;
  double i, width, height, length;
  success = true;
  /* Check series lengths. */
  lengthSet = false;
  length = 0.0;
  for(i = 0.0; i < settings->barPlotSeries->size(); i = i + 1.0){
    series = settings->barPlotSeries->at(i);
    if( !lengthSet ){
      length = series->ys->size();
      lengthSet = true;
    }else if(length != series->ys->size()){
      success = false;
    }
  }
  /* Check bounds. */
  if( !settings->autoBoundaries ){
    if(settings->yMin >= settings->yMax){
      success = false;
    }
  }
  /* Check padding. */
  if( !settings->autoPadding ){
    if(2.0*settings->xPadding >= settings->width){
      success = false;
    }
    if(2.0*settings->yPadding >= settings->height){
      success = false;
    }
  }
  /* Check width and height. */
  if(settings->width < 0.0){
    success = false;
  }
  if(settings->height < 0.0){
    success = false;
  }
  /* Check spacing */
  if( !settings->autoSpacing ){
    if(settings->groupSeparation < 0.0){
      success = false;
    }
    if(settings->barSeparation < 0.0){
      success = false;
    }
  }
  return success;
}
double GetMinimum(vector *data){
  double i, minimum;
  minimum = data->at(0);
  for(i = 0.0; i < data->size(); i = i + 1.0){
    minimum = fmin(minimum, data->at(i));
  }
  return minimum;
}
double GetMaximum(vector *data){
  double i, maximum;
  maximum = data->at(0);
  for(i = 0.0; i < data->size(); i = i + 1.0){
    maximum = fmax(maximum, data->at(i));
  }
  return maximum;
}
double RoundToDigits(double element, double digitsAfterPoint){
  return Round(element*pow(10.0, digitsAfterPoint))/pow(10.0, digitsAfterPoint);
}
double test(){
  double z;
  vector *gridlines;
  NumberReference *failures;
  StringArrayReference *labels;
  NumberArrayReference *labelPriorities;
  RGBABitmapImageReference *imageReference;
  vector *xs, *ys;
  failures = CreateNumberReference(0.0);
  imageReference = CreateRGBABitmapImageReference();
  labels = new StringArrayReference();
  labelPriorities = new NumberArrayReference();
  z = 10.0;
  gridlines = ComputeGridLinePositions( -z/2.0, z/2.0, labels, labelPriorities);
  AssertEquals(gridlines->size(), 11.0, failures);
  z = 9.0;
  gridlines = ComputeGridLinePositions( -z/2.0, z/2.0, labels, labelPriorities);
  AssertEquals(gridlines->size(), 19.0, failures);
  z = 8.0;
  gridlines = ComputeGridLinePositions( -z/2.0, z/2.0, labels, labelPriorities);
  AssertEquals(gridlines->size(), 17.0, failures);
  z = 7.0;
  gridlines = ComputeGridLinePositions( -z/2.0, z/2.0, labels, labelPriorities);
  AssertEquals(gridlines->size(), 15.0, failures);
  z = 6.0;
  gridlines = ComputeGridLinePositions( -z/2.0, z/2.0, labels, labelPriorities);
  AssertEquals(gridlines->size(), 13.0, failures);
  z = 5.0;
  gridlines = ComputeGridLinePositions( -z/2.0, z/2.0, labels, labelPriorities);
  AssertEquals(gridlines->size(), 21.0, failures);
  z = 4.0;
  gridlines = ComputeGridLinePositions( -z/2.0, z/2.0, labels, labelPriorities);
  AssertEquals(gridlines->size(), 17.0, failures);
  z = 3.0;
  gridlines = ComputeGridLinePositions( -z/2.0, z/2.0, labels, labelPriorities);
  AssertEquals(gridlines->size(), 31.0, failures);
  z = 2.0;
  gridlines = ComputeGridLinePositions( -z/2.0, z/2.0, labels, labelPriorities);
  AssertEquals(gridlines->size(), 21.0, failures);
  xs = new vector (5.0);
  xs->at(0) =  -2.0;
  xs->at(1) =  -1.0;
  xs->at(2) = 0.0;
  xs->at(3) = 1.0;
  xs->at(4) = 2.0;
  ys = new vector (5.0);
  ys->at(0) = 2.0;
  ys->at(1) =  -1.0;
  ys->at(2) =  -2.0;
  ys->at(3) =  -1.0;
  ys->at(4) = 2.0;
  DrawScatterPlot(imageReference, 800.0, 600.0, xs, ys);
  imageReference->image = DrawBarPlot(800.0, 600.0, ys);
  TestMapping(failures);
  TestMapping2(failures);
  return failures->numberValue;
}
void TestMapping(NumberReference *failures){
  ScatterPlotSeries *series;
  ScatterPlotSettings *settings;
  RGBABitmapImageReference *imageReference;
  double x1, y1;
  series = GetDefaultScatterPlotSeriesSettings();
  series->xs = new vector (5.0);
  series->xs->at(0) = -2.0;
  series->xs->at(1) = -1.0;
  series->xs->at(2) = 0.0;
  series->xs->at(3) = 1.0;
  series->xs->at(4) = 2.0;
  series->ys = new vector (5.0);
  series->ys->at(0) = -2.0;
  series->ys->at(1) = -1.0;
  series->ys->at(2) = -2.0;
  series->ys->at(3) = -1.0;
  series->ys->at(4) = 2.0;
  series->linearInterpolation = true;
  series->lineType = toVector(L"dashed");
  series->lineThickness = 2.0;
  series->color = GetGray(0.3);
  settings = GetDefaultScatterPlotSettings();
  settings->width = 600.0;
  settings->height = 400.0;
  settings->autoBoundaries = true;
  settings->autoPadding = true;
  settings->title = toVector(L"x^2 - 2");
  settings->xLabel = toVector(L"X axis");
  settings->yLabel = toVector(L"Y axis");
  settings->scatterPlotSeries = new vector (1.0);
  settings->scatterPlotSeries->at(0) = series;
  imageReference = CreateRGBABitmapImageReference();
  DrawScatterPlotFromSettings(imageReference, settings);
  x1 = MapXCoordinateAutoSettings( -1.0, imageReference->image, series->xs);
  y1 = MapYCoordinateAutoSettings( -1.0, imageReference->image, series->ys);
  AssertEquals(x1, 180.0, failures);
  AssertEquals(y1, 280.0, failures);
}
void TestMapping2(NumberReference *failures){
  vector *xs, *ys, *xs2, *ys2;
  double i, x, y, w, h, xMin, xMax, yMin, yMax;
  RGBABitmapImageReference *canvasReference;
  ScatterPlotSettings *settings;
  double points;
  double x1, y1;
  points = 300.0;
  w = 600.0*2.0;
  h = 300.0*2.0;
  xMin = 0.0;
  xMax = 150.0;
  yMin = 0.0;
  yMax = 1.0;
  xs = new vector (points);
  ys = new vector (points);
  xs2 = new vector (points);
  ys2 = new vector (points);
  for(i = 0.0; i < points; i = i + 1.0){
    x = xMin + (xMax - xMin)/(points - 1.0)*i;
    /* points - 1d is to ensure both extremeties are included. */
    y = x/(x + 7.0);
    xs->at(i) = x;
    ys->at(i) = y;
    y = 1.4*x/(x + 7.0)*(1.0 - (atan((x/1.5 - 30.0)/5.0)/1.6 + 1.0)/2.0);
    xs2->at(i) = x;
    ys2->at(i) = y;
  }
  settings = GetDefaultScatterPlotSettings();
  settings->scatterPlotSeries = new vector (2.0);
  settings->scatterPlotSeries->at(0) = new ScatterPlotSeries();
  settings->scatterPlotSeries->at(0)->xs = xs;
  settings->scatterPlotSeries->at(0)->ys = ys;
  settings->scatterPlotSeries->at(0)->linearInterpolation = true;
  settings->scatterPlotSeries->at(0)->lineType = toVector(L"solid");
  settings->scatterPlotSeries->at(0)->lineThickness = 3.0;
  settings->scatterPlotSeries->at(0)->color = CreateRGBColor(1.0, 0.0, 0.0);
  settings->scatterPlotSeries->at(1) = new ScatterPlotSeries();
  settings->scatterPlotSeries->at(1)->xs = xs2;
  settings->scatterPlotSeries->at(1)->ys = ys2;
  settings->scatterPlotSeries->at(1)->linearInterpolation = true;
  settings->scatterPlotSeries->at(1)->lineType = toVector(L"solid");
  settings->scatterPlotSeries->at(1)->lineThickness = 3.0;
  settings->scatterPlotSeries->at(1)->color = CreateRGBColor(0.0, 0.0, 1.0);
  settings->autoBoundaries = false;
  settings->xMin = xMin;
  settings->xMax = xMax;
  settings->yMin = yMin;
  settings->yMax = yMax;
  settings->yLabel = toVector(L"");
  settings->xLabel = toVector(L"Features");
  settings->title = toVector(L"");
  settings->width = w;
  settings->height = h;
  canvasReference = CreateRGBABitmapImageReference();
  DrawScatterPlotFromSettings(canvasReference, settings);
  x1 = MapXCoordinateBasedOnSettings(27.0, settings);
  y1 = MapYCoordinateBasedOnSettings(1.0, settings);
  AssertEquals(floor(x1), 292.0, failures);
  AssertEquals(y1, 60.0, failures);
}
RGBA *GetBlack(){
  RGBA *black;
  black = new RGBA();
  black->a = 1.0;
  black->r = 0.0;
  black->g = 0.0;
  black->b = 0.0;
  return black;
}
RGBA *GetWhite(){
  RGBA *white;
  white = new RGBA();
  white->a = 1.0;
  white->r = 1.0;
  white->g = 1.0;
  white->b = 1.0;
  return white;
}
RGBA *GetTransparent(){
  RGBA *transparent;
  transparent = new RGBA();
  transparent->a = 0.0;
  transparent->r = 0.0;
  transparent->g = 0.0;
  transparent->b = 0.0;
  return transparent;
}
RGBA *GetGray(double percentage){
  RGBA *black;
  black = new RGBA();
  black->a = 1.0;
  black->r = 1.0 - percentage;
  black->g = 1.0 - percentage;
  black->b = 1.0 - percentage;
  return black;
}
RGBA *CreateRGBColor(double r, double g, double b){
  RGBA *color;
  color = new RGBA();
  color->a = 1.0;
  color->r = r;
  color->g = g;
  color->b = b;
  return color;
}
RGBA *CreateRGBAColor(double r, double g, double b, double a){
  RGBA *color;
  color = new RGBA();
  color->a = a;
  color->r = r;
  color->g = g;
  color->b = b;
  return color;
}
RGBABitmapImage *CreateImage(double w, double h, RGBA *color){
  RGBABitmapImage *image;
  double i, j;
  image = new RGBABitmapImage();
  image->x = new vector (w);
  for(i = 0.0; i < w; i = i + 1.0){
    image->x->at(i) = new RGBABitmap();
    image->x->at(i)->y = new vector (h);
    for(j = 0.0; j < h; j = j + 1.0){
      image->x->at(i)->y->at(j) = new RGBA();
      SetPixel(image, i, j, color);
    }
  }
  return image;
}
void DeleteImage(RGBABitmapImage *image){
  double i, j, w, h;
  w = ImageWidth(image);
  h = ImageHeight(image);
  for(i = 0.0; i < w; i = i + 1.0){
    for(j = 0.0; j < h; j = j + 1.0){
      delete image->x->at(i)->y->at(j);
    }
    delete image->x->at(i);
  }
  delete image;
}
double ImageWidth(RGBABitmapImage *image){
  return image->x->size();
}
double ImageHeight(RGBABitmapImage *image){
  double height;
  if(ImageWidth(image) == 0.0){
    height = 0.0;
  }else{
    height = image->x->at(0)->y->size();
  }
  return height;
}
void SetPixel(RGBABitmapImage *image, double x, double y, RGBA *color){
  if(x >= 0.0 && x < ImageWidth(image) && y >= 0.0 && y < ImageHeight(image)){
    image->x->at(x)->y->at(y)->a = color->a;
    image->x->at(x)->y->at(y)->r = color->r;
    image->x->at(x)->y->at(y)->g = color->g;
    image->x->at(x)->y->at(y)->b = color->b;
  }
}
void DrawPixel(RGBABitmapImage *image, double x, double y, RGBA *color){
  double ra, ga, ba, aa;
  double rb, gb, bb, ab;
  double ro, go, bo, ao;
  if(x >= 0.0 && x < ImageWidth(image) && y >= 0.0 && y < ImageHeight(image)){
    ra = color->r;
    ga = color->g;
    ba = color->b;
    aa = color->a;
    rb = image->x->at(x)->y->at(y)->r;
    gb = image->x->at(x)->y->at(y)->g;
    bb = image->x->at(x)->y->at(y)->b;
    ab = image->x->at(x)->y->at(y)->a;
    ao = CombineAlpha(aa, ab);
    ro = AlphaBlend(ra, aa, rb, ab, ao);
    go = AlphaBlend(ga, aa, gb, ab, ao);
    bo = AlphaBlend(ba, aa, bb, ab, ao);
    image->x->at(x)->y->at(y)->r = ro;
    image->x->at(x)->y->at(y)->g = go;
    image->x->at(x)->y->at(y)->b = bo;
    image->x->at(x)->y->at(y)->a = ao;
  }
}
double CombineAlpha(double as, double ad){
  return as + ad*(1.0 - as);
}
double AlphaBlend(double cs, double as, double cd, double ad, double ao){
  return (cs*as + cd*ad*(1.0 - as))/ao;
}
void DrawHorizontalLine1px(RGBABitmapImage *image, double x, double y, double length, RGBA *color){
  double i;
  for(i = 0.0; i < length; i = i + 1.0){
    DrawPixel(image, x + i, y, color);
  }
}
void DrawVerticalLine1px(RGBABitmapImage *image, double x, double y, double height, RGBA *color){
  double i;
  for(i = 0.0; i < height; i = i + 1.0){
    DrawPixel(image, x, y + i, color);
  }
}
void DrawRectangle1px(RGBABitmapImage *image, double x, double y, double width, double height, RGBA *color){
  DrawHorizontalLine1px(image, x, y, width + 1.0, color);
  DrawVerticalLine1px(image, x, y + 1.0, height + 1.0 - 1.0, color);
  DrawVerticalLine1px(image, x + width, y + 1.0, height + 1.0 - 1.0, color);
  DrawHorizontalLine1px(image, x + 1.0, y + height, width + 1.0 - 2.0, color);
}
void DrawImageOnImage(RGBABitmapImage *dst, RGBABitmapImage *src, double topx, double topy){
  double y, x;
  for(y = 0.0; y < ImageHeight(src); y = y + 1.0){
    for(x = 0.0; x < ImageWidth(src); x = x + 1.0){
      if(topx + x >= 0.0 && topx + x < ImageWidth(dst) && topy + y >= 0.0 && topy + y < ImageHeight(dst)){
        DrawPixel(dst, topx + x, topy + y, src->x->at(x)->y->at(y));
      }
    }
  }
}
void DrawLine1px(RGBABitmapImage *image, double x0, double y0, double x1, double y1, RGBA *color){
  XiaolinWusLineAlgorithm(image, x0, y0, x1, y1, color);
}
void XiaolinWusLineAlgorithm(RGBABitmapImage *image, double x0, double y0, double x1, double y1, RGBA *color){
  bool steep;
  double x, t, dx, dy, g, xEnd, yEnd, xGap, xpxl1, ypxl1, intery, xpxl2, ypxl2, olda;
  olda = color->a;
  steep = abs(y1 - y0) > abs(x1 - x0);
  if(steep){
    t = x0;
    x0 = y0;
    y0 = t;
    t = x1;
    x1 = y1;
    y1 = t;
  }
  if(x0 > x1){
    t = x0;
    x0 = x1;
    x1 = t;
    t = y0;
    y0 = y1;
    y1 = t;
  }
  dx = x1 - x0;
  dy = y1 - y0;
  g = dy/dx;
  if(dx == 0.0){
    g = 1.0;
  }
  xEnd = Round(x0);
  yEnd = y0 + g*(xEnd - x0);
  xGap = OneMinusFractionalPart(x0 + 0.5);
  xpxl1 = xEnd;
  ypxl1 = floor(yEnd);
  if(steep){
    DrawPixel(image, ypxl1, xpxl1, SetBrightness(color, OneMinusFractionalPart(yEnd)*xGap));
    DrawPixel(image, ypxl1 + 1.0, xpxl1, SetBrightness(color, FractionalPart(yEnd)*xGap));
  }else{
    DrawPixel(image, xpxl1, ypxl1, SetBrightness(color, OneMinusFractionalPart(yEnd)*xGap));
    DrawPixel(image, xpxl1, ypxl1 + 1.0, SetBrightness(color, FractionalPart(yEnd)*xGap));
  }
  intery = yEnd + g;
  xEnd = Round(x1);
  yEnd = y1 + g*(xEnd - x1);
  xGap = FractionalPart(x1 + 0.5);
  xpxl2 = xEnd;
  ypxl2 = floor(yEnd);
  if(steep){
    DrawPixel(image, ypxl2, xpxl2, SetBrightness(color, OneMinusFractionalPart(yEnd)*xGap));
    DrawPixel(image, ypxl2 + 1.0, xpxl2, SetBrightness(color, FractionalPart(yEnd)*xGap));
  }else{
    DrawPixel(image, xpxl2, ypxl2, SetBrightness(color, OneMinusFractionalPart(yEnd)*xGap));
    DrawPixel(image, xpxl2, ypxl2 + 1.0, SetBrightness(color, FractionalPart(yEnd)*xGap));
  }
  if(steep){
    for(x = xpxl1 + 1.0; x <= xpxl2 - 1.0; x = x + 1.0){
      DrawPixel(image, floor(intery), x, SetBrightness(color, OneMinusFractionalPart(intery)));
      DrawPixel(image, floor(intery) + 1.0, x, SetBrightness(color, FractionalPart(intery)));
      intery = intery + g;
    }
  }else{
    for(x = xpxl1 + 1.0; x <= xpxl2 - 1.0; x = x + 1.0){
      DrawPixel(image, x, floor(intery), SetBrightness(color, OneMinusFractionalPart(intery)));
      DrawPixel(image, x, floor(intery) + 1.0, SetBrightness(color, FractionalPart(intery)));
      intery = intery + g;
    }
  }
  color->a = olda;
}
double OneMinusFractionalPart(double x){
  return 1.0 - FractionalPart(x);
}
double FractionalPart(double x){
  return x - floor(x);
}
RGBA *SetBrightness(RGBA *color, double newBrightness){
  color->a = newBrightness;
  return color;
}
void DrawQuadraticBezierCurve(RGBABitmapImage *image, double x0, double y0, double cx, double cy, double x1, double y1, RGBA *color){
  double t, dt, dx, dy;
  NumberReference *xs, *ys, *xe, *ye;
  dx = abs(x0 - x1);
  dy = abs(y0 - y1);
  dt = 1.0/sqrt(pow(dx, 2.0) + pow(dy, 2.0));
  xs = new NumberReference();
  ys = new NumberReference();
  xe = new NumberReference();
  ye = new NumberReference();
  QuadraticBezierPoint(x0, y0, cx, cy, x1, y1, 0.0, xs, ys);
  for(t = dt; t <= 1.0; t = t + dt){
    QuadraticBezierPoint(x0, y0, cx, cy, x1, y1, t, xe, ye);
    DrawLine1px(image, xs->numberValue, ys->numberValue, xe->numberValue, ye->numberValue, color);
    xs->numberValue = xe->numberValue;
    ys->numberValue = ye->numberValue;
  }
  delete xs;
  delete ys;
  delete xe;
  delete ye;
}
void QuadraticBezierPoint(double x0, double y0, double cx, double cy, double x1, double y1, double t, NumberReference *x, NumberReference *y){
  x->numberValue = pow(1.0 - t, 2.0)*x0 + (1.0 - t)*2.0*t*cx + pow(t, 2.0)*x1;
  y->numberValue = pow(1.0 - t, 2.0)*y0 + (1.0 - t)*2.0*t*cy + pow(t, 2.0)*y1;
}
void DrawCubicBezierCurve(RGBABitmapImage *image, double x0, double y0, double c0x, double c0y, double c1x, double c1y, double x1, double y1, RGBA *color){
  double t, dt, dx, dy;
  NumberReference *xs, *ys, *xe, *ye;
  dx = abs(x0 - x1);
  dy = abs(y0 - y1);
  dt = 1.0/sqrt(pow(dx, 2.0) + pow(dy, 2.0));
  xs = new NumberReference();
  ys = new NumberReference();
  xe = new NumberReference();
  ye = new NumberReference();
  CubicBezierPoint(x0, y0, c0x, c0y, c1x, c1y, x1, y1, 0.0, xs, ys);
  for(t = dt; t <= 1.0; t = t + dt){
    CubicBezierPoint(x0, y0, c0x, c0y, c1x, c1y, x1, y1, t, xe, ye);
    DrawLine1px(image, xs->numberValue, ys->numberValue, xe->numberValue, ye->numberValue, color);
    xs->numberValue = xe->numberValue;
    ys->numberValue = ye->numberValue;
  }
  delete xs;
  delete ys;
  delete xe;
  delete ye;
}
void CubicBezierPoint(double x0, double y0, double c0x, double c0y, double c1x, double c1y, double x1, double y1, double t, NumberReference *x, NumberReference *y){
  x->numberValue = pow(1.0 - t, 3.0)*x0 + pow(1.0 - t, 2.0)*3.0*t*c0x + (1.0 - t)*3.0*pow(t, 2.0)*c1x + pow(t, 3.0)*x1;
  y->numberValue = pow(1.0 - t, 3.0)*y0 + pow(1.0 - t, 2.0)*3.0*t*c0y + (1.0 - t)*3.0*pow(t, 2.0)*c1y + pow(t, 3.0)*y1;
}
RGBABitmapImage *CopyImage(RGBABitmapImage *image){
  RGBABitmapImage *copy;
  double i, j;
  copy = CreateImage(ImageWidth(image), ImageHeight(image), GetTransparent());
  for(i = 0.0; i < ImageWidth(image); i = i + 1.0){
    for(j = 0.0; j < ImageHeight(image); j = j + 1.0){
      SetPixel(copy, i, j, image->x->at(i)->y->at(j));
    }
  }
  return copy;
}
RGBA *GetImagePixel(RGBABitmapImage *image, double x, double y){
  return image->x->at(x)->y->at(y);
}
void HorizontalFlip(RGBABitmapImage *img){
  double y, x;
  double tmp;
  RGBA *c1, *c2;
  for(y = 0.0; y < ImageHeight(img); y = y + 1.0){
    for(x = 0.0; x < ImageWidth(img)/2.0; x = x + 1.0){
      c1 = img->x->at(x)->y->at(y);
      c2 = img->x->at(ImageWidth(img) - 1.0 - x)->y->at(y);
      tmp = c1->a;
      c1->a = c2->a;
      c2->a = tmp;
      tmp = c1->r;
      c1->r = c2->r;
      c2->r = tmp;
      tmp = c1->g;
      c1->g = c2->g;
      c2->g = tmp;
      tmp = c1->b;
      c1->b = c2->b;
      c2->b = tmp;
    }
  }
}
void DrawFilledRectangle(RGBABitmapImage *image, double x, double y, double w, double h, RGBA *color){
  double i, j;
  for(i = 0.0; i < w; i = i + 1.0){
    for(j = 0.0; j < h; j = j + 1.0){
      SetPixel(image, x + i, y + j, color);
    }
  }
}
RGBABitmapImage *RotateAntiClockwise90Degrees(RGBABitmapImage *image){
  RGBABitmapImage *rotated;
  double x, y;
  rotated = CreateImage(ImageHeight(image), ImageWidth(image), GetBlack());
  for(y = 0.0; y < ImageHeight(image); y = y + 1.0){
    for(x = 0.0; x < ImageWidth(image); x = x + 1.0){
      SetPixel(rotated, y, ImageWidth(image) - 1.0 - x, GetImagePixel(image, x, y));
    }
  }
  return rotated;
}
void DrawCircle(RGBABitmapImage *canvas, double xCenter, double yCenter, double radius, RGBA *color){
  DrawCircleBasicAlgorithm(canvas, xCenter, yCenter, radius, color);
}
void BresenhamsCircleDrawingAlgorithm(RGBABitmapImage *canvas, double xCenter, double yCenter, double radius, RGBA *color){
  double x, y, delta;
  y = radius;
  x = 0.0;
  delta = 3.0 - 2.0*radius;
  for(; y >= x; x = x + 1.0){
    DrawLine1px(canvas, xCenter + x, yCenter + y, xCenter + x, yCenter + y, color);
    DrawLine1px(canvas, xCenter + x, yCenter - y, xCenter + x, yCenter - y, color);
    DrawLine1px(canvas, xCenter - x, yCenter + y, xCenter - x, yCenter + y, color);
    DrawLine1px(canvas, xCenter - x, yCenter - y, xCenter - x, yCenter - y, color);
    DrawLine1px(canvas, xCenter - y, yCenter + x, xCenter - y, yCenter + x, color);
    DrawLine1px(canvas, xCenter - y, yCenter - x, xCenter - y, yCenter - x, color);
    DrawLine1px(canvas, xCenter + y, yCenter + x, xCenter + y, yCenter + x, color);
    DrawLine1px(canvas, xCenter + y, yCenter - x, xCenter + y, yCenter - x, color);
    if(delta < 0.0){
      delta = delta + 4.0*x + 6.0;
    }else{
      delta = delta + 4.0*(x - y) + 10.0;
      y = y - 1.0;
    }
  }
}
void DrawCircleMidpointAlgorithm(RGBABitmapImage *canvas, double xCenter, double yCenter, double radius, RGBA *color){
  double d, x, y;
  d = floor((5.0 - radius*4.0)/4.0);
  x = 0.0;
  y = radius;
  for(; x <= y; x = x + 1.0){
    DrawPixel(canvas, xCenter + x, yCenter + y, color);
    DrawPixel(canvas, xCenter + x, yCenter - y, color);
    DrawPixel(canvas, xCenter - x, yCenter + y, color);
    DrawPixel(canvas, xCenter - x, yCenter - y, color);
    DrawPixel(canvas, xCenter + y, yCenter + x, color);
    DrawPixel(canvas, xCenter + y, yCenter - x, color);
    DrawPixel(canvas, xCenter - y, yCenter + x, color);
    DrawPixel(canvas, xCenter - y, yCenter - x, color);
    if(d < 0.0){
      d = d + 2.0*x + 1.0;
    }else{
      d = d + 2.0*(x - y) + 1.0;
      y = y - 1.0;
    }
  }
}
void DrawCircleBasicAlgorithm(RGBABitmapImage *canvas, double xCenter, double yCenter, double radius, RGBA *color){
  double pixels, a, da, dx, dy;
  /* Place the circle in the center of the pixel. */
  xCenter = floor(xCenter) + 0.5;
  yCenter = floor(yCenter) + 0.5;
  pixels = 2.0*M_PI*radius;
  /* Below a radius of 10 pixels, over-compensate to get a smoother circle. */
  if(radius < 10.0){
    pixels = pixels*10.0;
  }
  da = 2.0*M_PI/pixels;
  for(a = 0.0; a < 2.0*M_PI; a = a + da){
    dx = cos(a)*radius;
    dy = sin(a)*radius;
    /* Floor to get the pixel coordinate. */
    DrawPixel(canvas, floor(xCenter + dx), floor(yCenter + dy), color);
  }
}
void DrawFilledCircle(RGBABitmapImage *canvas, double x, double y, double r, RGBA *color){
  DrawFilledCircleBasicAlgorithm(canvas, x, y, r, color);
}
void DrawFilledCircleMidpointAlgorithm(RGBABitmapImage *canvas, double xCenter, double yCenter, double radius, RGBA *color){
  double d, x, y;
  d = floor((5.0 - radius*4.0)/4.0);
  x = 0.0;
  y = radius;
  for(; x <= y; x = x + 1.0){
    DrawLineBresenhamsAlgorithm(canvas, xCenter + x, yCenter + y, xCenter - x, yCenter + y, color);
    DrawLineBresenhamsAlgorithm(canvas, xCenter + x, yCenter - y, xCenter - x, yCenter - y, color);
    DrawLineBresenhamsAlgorithm(canvas, xCenter + y, yCenter + x, xCenter - y, yCenter + x, color);
    DrawLineBresenhamsAlgorithm(canvas, xCenter + y, yCenter - x, xCenter - y, yCenter - x, color);
    if(d < 0.0){
      d = d + 2.0*x + 1.0;
    }else{
      d = d + 2.0*(x - y) + 1.0;
      y = y - 1.0;
    }
  }
}
void DrawFilledCircleBasicAlgorithm(RGBABitmapImage *canvas, double xCenter, double yCenter, double radius, RGBA *color){
  double pixels, a, da, dx, dy;
  /* Place the circle in the center of the pixel. */
  xCenter = floor(xCenter) + 0.5;
  yCenter = floor(yCenter) + 0.5;
  pixels = 2.0*M_PI*radius;
  /* Below a radius of 10 pixels, over-compensate to get a smoother circle. */
  if(radius < 10.0){
    pixels = pixels*10.0;
  }
  da = 2.0*M_PI/pixels;
  /* Draw lines for a half-circle to fill an entire circle. */
  for(a = 0.0; a < M_PI; a = a + da){
    dx = cos(a)*radius;
    dy = sin(a)*radius;
    /* Floor to get the pixel coordinate. */
    DrawVerticalLine1px(canvas, floor(xCenter - dx), floor(yCenter - dy), floor(2.0*dy) + 1.0, color);
  }
}
void DrawTriangle(RGBABitmapImage *canvas, double xCenter, double yCenter, double height, RGBA *color){
  double x1, y1, x2, y2, x3, y3;
  x1 = floor(xCenter + 0.5);
  y1 = floor(floor(yCenter + 0.5) - height);
  x2 = x1 - 2.0*height*tan(M_PI/6.0);
  y2 = floor(y1 + 2.0*height);
  x3 = x1 + 2.0*height*tan(M_PI/6.0);
  y3 = floor(y1 + 2.0*height);
  DrawLine1px(canvas, x1, y1, x2, y2, color);
  DrawLine1px(canvas, x1, y1, x3, y3, color);
  DrawLine1px(canvas, x2, y2, x3, y3, color);
}
void DrawFilledTriangle(RGBABitmapImage *canvas, double xCenter, double yCenter, double height, RGBA *color){
  double i, offset, x1, y1;
  x1 = floor(xCenter + 0.5);
  y1 = floor(floor(yCenter + 0.5) - height);
  for(i = 0.0; i <= 2.0*height; i = i + 1.0){
    offset = floor(i*tan(M_PI/6.0));
    DrawHorizontalLine1px(canvas, x1 - offset, y1 + i, 2.0*offset, color);
  }
}
void DrawLine(RGBABitmapImage *canvas, double x1, double y1, double x2, double y2, double thickness, RGBA *color){
  DrawLineBresenhamsAlgorithmThick(canvas, x1, y1, x2, y2, thickness, color);
}
void DrawLineBresenhamsAlgorithmThick(RGBABitmapImage *canvas, double x1, double y1, double x2, double y2, double thickness, RGBA *color){
  double x, y, dx, dy, incX, incY, pdx, pdy, es, el, err, t, r;
  dx = x2 - x1;
  dy = y2 - y1;
  incX = Sign(dx);
  incY = Sign(dy);
  dx = abs(dx);
  dy = abs(dy);
  if(dx > dy){
    pdx = incX;
    pdy = 0.0;
    es = dy;
    el = dx;
  }else{
    pdx = 0.0;
    pdy = incY;
    es = dx;
    el = dy;
  }
  x = x1;
  y = y1;
  err = el/2.0;
  if(thickness >= 3.0){
    r = thickness/2.0;
    DrawCircle(canvas, x, y, r, color);
  }else if(floor(thickness) == 2.0){
    DrawFilledRectangle(canvas, x, y, 2.0, 2.0, color);
  }else if(floor(thickness) == 1.0){
    DrawPixel(canvas, x, y, color);
  }
  for(t = 0.0; t < el; t = t + 1.0){
    err = err - es;
    if(err < 0.0){
      err = err + el;
      x = x + incX;
      y = y + incY;
    }else{
      x = x + pdx;
      y = y + pdy;
    }
    if(thickness >= 3.0){
      r = thickness/2.0;
      DrawCircle(canvas, x, y, r, color);
    }else if(floor(thickness) == 2.0){
      DrawFilledRectangle(canvas, x, y, 2.0, 2.0, color);
    }else if(floor(thickness) == 1.0){
      DrawPixel(canvas, x, y, color);
    }
  }
}
void DrawLineBresenhamsAlgorithm(RGBABitmapImage *canvas, double x1, double y1, double x2, double y2, RGBA *color){
  double x, y, dx, dy, incX, incY, pdx, pdy, es, el, err, t;
  dx = x2 - x1;
  dy = y2 - y1;
  incX = Sign(dx);
  incY = Sign(dy);
  dx = abs(dx);
  dy = abs(dy);
  if(dx > dy){
    pdx = incX;
    pdy = 0.0;
    es = dy;
    el = dx;
  }else{
    pdx = 0.0;
    pdy = incY;
    es = dx;
    el = dy;
  }
  x = x1;
  y = y1;
  err = el/2.0;
  DrawPixel(canvas, x, y, color);
  for(t = 0.0; t < el; t = t + 1.0){
    err = err - es;
    if(err < 0.0){
      err = err + el;
      x = x + incX;
      y = y + incY;
    }else{
      x = x + pdx;
      y = y + pdy;
    }
    DrawPixel(canvas, x, y, color);
  }
}
void DrawLineBresenhamsAlgorithmThickPatterned(RGBABitmapImage *canvas, double x1, double y1, double x2, double y2, double thickness, vector *pattern, NumberReference *offset, RGBA *color){
  double x, y, dx, dy, incX, incY, pdx, pdy, es, el, err, t, r;
  dx = x2 - x1;
  dy = y2 - y1;
  incX = Sign(dx);
  incY = Sign(dy);
  dx = abs(dx);
  dy = abs(dy);
  if(dx > dy){
    pdx = incX;
    pdy = 0.0;
    es = dy;
    el = dx;
  }else{
    pdx = 0.0;
    pdy = incY;
    es = dx;
    el = dy;
  }
  x = x1;
  y = y1;
  err = el/2.0;
  offset->numberValue = fmod(offset->numberValue + 1.0, pattern->size()*thickness);
  if(pattern->at(floor(offset->numberValue/thickness))){
    if(thickness >= 3.0){
      r = thickness/2.0;
      DrawCircle(canvas, x, y, r, color);
    }else if(floor(thickness) == 2.0){
      DrawFilledRectangle(canvas, x, y, 2.0, 2.0, color);
    }else if(floor(thickness) == 1.0){
      DrawPixel(canvas, x, y, color);
    }
  }
  for(t = 0.0; t < el; t = t + 1.0){
    err = err - es;
    if(err < 0.0){
      err = err + el;
      x = x + incX;
      y = y + incY;
    }else{
      x = x + pdx;
      y = y + pdy;
    }
    offset->numberValue = fmod(offset->numberValue + 1.0, pattern->size()*thickness);
    if(pattern->at(floor(offset->numberValue/thickness))){
      if(thickness >= 3.0){
        r = thickness/2.0;
        DrawCircle(canvas, x, y, r, color);
      }else if(floor(thickness) == 2.0){
        DrawFilledRectangle(canvas, x, y, 2.0, 2.0, color);
      }else if(floor(thickness) == 1...
SOLUTION.PDF

Answer To This Question Is Available To Download

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here