Skip to content

Commit 0e23d6a

Browse files
Fixed bug in coordinate mapper
1 parent 3eaec98 commit 0e23d6a

File tree

14 files changed

+2592
-402
lines changed

14 files changed

+2592
-402
lines changed

C/pbPlots.c

Lines changed: 237 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -460,11 +460,51 @@ double MapXCoordinate(double x, double xMin, double xMax, double xPixelMin, doub
460460
return x;
461461
}
462462
double MapXCoordinateAutoSettings(double x, RGBABitmapImage *image, double *xs, size_t xsLength){
463-
return MapXCoordinate(x, GetMinimum(xs, xsLength), GetMaximum(xs, xsLength) - GetMinimum(xs, xsLength), GetDefaultPaddingPercentage()*ImageWidth(image), (1.0 - GetDefaultPaddingPercentage())*ImageWidth(image));
463+
return MapXCoordinate(x, GetMinimum(xs, xsLength), GetMaximum(xs, xsLength), GetDefaultPaddingPercentage()*ImageWidth(image), (1.0 - GetDefaultPaddingPercentage())*ImageWidth(image));
464464
}
465465
double MapYCoordinateAutoSettings(double y, RGBABitmapImage *image, double *ys, size_t ysLength){
466466
return MapYCoordinate(y, GetMinimum(ys, ysLength), GetMaximum(ys, ysLength), GetDefaultPaddingPercentage()*ImageHeight(image), (1.0 - GetDefaultPaddingPercentage())*ImageHeight(image));
467467
}
468+
double MapXCoordinateBasedOnSettings(double x, ScatterPlotSettings *settings){
469+
double xMin, xMax, xPadding, xPixelMin, xPixelMax;
470+
Rectangle *boundaries;
471+
472+
boundaries = (Rectangle *)malloc(sizeof(Rectangle));
473+
ComputeBoundariesBasedOnSettings(settings, boundaries);
474+
xMin = boundaries->x1;
475+
xMax = boundaries->x2;
476+
477+
if(settings->autoPadding){
478+
xPadding = floor(GetDefaultPaddingPercentage()*settings->width);
479+
}else{
480+
xPadding = settings->xPadding;
481+
}
482+
483+
xPixelMin = xPadding;
484+
xPixelMax = settings->width - xPadding;
485+
486+
return MapXCoordinate(x, xMin, xMax, xPixelMin, xPixelMax);
487+
}
488+
double MapYCoordinateBasedOnSettings(double y, ScatterPlotSettings *settings){
489+
double yMin, yMax, yPadding, yPixelMin, yPixelMax;
490+
Rectangle *boundaries;
491+
492+
boundaries = (Rectangle *)malloc(sizeof(Rectangle));
493+
ComputeBoundariesBasedOnSettings(settings, boundaries);
494+
yMin = boundaries->y1;
495+
yMax = boundaries->y2;
496+
497+
if(settings->autoPadding){
498+
yPadding = floor(GetDefaultPaddingPercentage()*settings->height);
499+
}else{
500+
yPadding = settings->yPadding;
501+
}
502+
503+
yPixelMin = yPadding;
504+
yPixelMax = settings->height - yPadding;
505+
506+
return MapYCoordinate(y, yMin, yMax, yPixelMin, yPixelMax);
507+
}
468508
double GetDefaultPaddingPercentage(){
469509
return 0.10;
470510
}
@@ -503,10 +543,10 @@ ScatterPlotSettings *GetDefaultScatterPlotSettings(){
503543
settings->yPadding = 0.0;
504544
settings->title = L"";
505545
settings->titleLength = wcslen(settings->title);
506-
settings->yLabel = L"";
507-
settings->yLabelLength = wcslen(settings->yLabel);
508546
settings->xLabel = L"";
509547
settings->xLabelLength = wcslen(settings->xLabel);
548+
settings->yLabel = L"";
549+
settings->yLabelLength = wcslen(settings->yLabel);
510550
settings->scatterPlotSeries = (ScatterPlotSeries**)malloc(sizeof(ScatterPlotSeries) * 0.0);
511551
settings->scatterPlotSeriesLength = 0.0;
512552
settings->showGrid = true;
@@ -560,6 +600,7 @@ void DrawScatterPlot(RGBABitmapImageReference *canvasReference, double width, do
560600
}
561601
_Bool DrawScatterPlotFromSettings(RGBABitmapImageReference *canvasReference, ScatterPlotSettings *settings){
562602
double xMin, xMax, yMin, yMax, xLength, yLength, i, x, y, xPrev, yPrev, px, py, pxPrev, pyPrev, originX, originY, p, l, plot;
603+
Rectangle *boundaries;
563604
double xPadding, yPadding, originXPixels, originYPixels;
564605
double xPixelMin, yPixelMin, xPixelMax, yPixelMax, xLengthPixels, yLengthPixels, axisLabelPadding;
565606
NumberReference *nextRectangle, *x1Ref, *y1Ref, *x2Ref, *y2Ref, *patternOffset;
@@ -588,53 +629,32 @@ _Bool DrawScatterPlotFromSettings(RGBABitmapImageReference *canvasReference, Sca
588629

589630
if(success){
590631

591-
if(settings->scatterPlotSeriesLength >= 1.0){
592-
xMin = GetMinimum(settings->scatterPlotSeries[0]->xs, settings->scatterPlotSeries[0]->xsLength);
593-
xMax = GetMaximum(settings->scatterPlotSeries[0]->xs, settings->scatterPlotSeries[0]->xsLength);
594-
yMin = GetMinimum(settings->scatterPlotSeries[0]->ys, settings->scatterPlotSeries[0]->ysLength);
595-
yMax = GetMaximum(settings->scatterPlotSeries[0]->ys, settings->scatterPlotSeries[0]->ysLength);
596-
}else{
597-
xMin = -10.0;
598-
xMax = 10.0;
599-
yMin = -10.0;
600-
yMax = 10.0;
601-
}
602-
603-
if( !settings->autoBoundaries ){
604-
xMin = settings->xMin;
605-
xMax = settings->xMax;
606-
yMin = settings->yMin;
607-
yMax = settings->yMax;
608-
}else{
609-
for(plot = 1.0; plot < settings->scatterPlotSeriesLength; plot = plot + 1.0){
610-
sp = settings->scatterPlotSeries[(int)(plot)];
611-
612-
xMin = fmin(xMin, GetMinimum(sp->xs, sp->xsLength));
613-
xMax = fmax(xMax, GetMaximum(sp->xs, sp->xsLength));
614-
yMin = fmin(yMin, GetMinimum(sp->ys, sp->ysLength));
615-
yMax = fmax(yMax, GetMaximum(sp->ys, sp->ysLength));
616-
}
617-
}
632+
boundaries = (Rectangle *)malloc(sizeof(Rectangle));
633+
ComputeBoundariesBasedOnSettings(settings, boundaries);
634+
xMin = boundaries->x1;
635+
yMin = boundaries->y1;
636+
xMax = boundaries->x2;
637+
yMax = boundaries->y2;
618638

619639
xLength = xMax - xMin;
620640
yLength = yMax - yMin;
621641

622642
if(settings->autoPadding){
623-
xPadding = floor(GetDefaultPaddingPercentage()*ImageWidth(canvas));
624-
yPadding = floor(GetDefaultPaddingPercentage()*ImageHeight(canvas));
643+
xPadding = floor(GetDefaultPaddingPercentage()*settings->width);
644+
yPadding = floor(GetDefaultPaddingPercentage()*settings->height);
625645
}else{
626646
xPadding = settings->xPadding;
627647
yPadding = settings->yPadding;
628648
}
629649

630650
/* Draw title */
631-
DrawText(canvas, floor(ImageWidth(canvas)/2.0 - GetTextWidth(settings->title, settings->titleLength)/2.0), floor(yPadding/3.0), settings->title, settings->titleLength, GetBlack());
651+
DrawText(canvas, floor(settings->width/2.0 - GetTextWidth(settings->title, settings->titleLength)/2.0), floor(yPadding/3.0), settings->title, settings->titleLength, GetBlack());
632652

633653
/* Draw grid */
634654
xPixelMin = xPadding;
635655
yPixelMin = yPadding;
636-
xPixelMax = ImageWidth(canvas) - xPadding;
637-
yPixelMax = ImageHeight(canvas) - yPadding;
656+
xPixelMax = settings->width - xPadding;
657+
yPixelMax = settings->height - yPadding;
638658
xLengthPixels = xPixelMax - xPixelMin;
639659
yLengthPixels = yPixelMax - yPixelMin;
640660
DrawRectangle1px(canvas, xPixelMin, yPixelMin, xLengthPixels, yLengthPixels, settings->gridColor);
@@ -755,8 +775,8 @@ if(settings->yAxisLeft){
755775
}
756776

757777
/* Draw origin axis titles. */
758-
DrawTextUpwards(canvas, 10.0, floor(originTextYPixels - GetTextWidth(settings->xLabel, settings->xLabelLength)/2.0), settings->xLabel, settings->xLabelLength, GetBlack());
759-
DrawText(canvas, floor(originTextXPixels - GetTextWidth(settings->yLabel, settings->yLabelLength)/2.0), yPixelMax + axisLabelPadding, settings->yLabel, settings->yLabelLength, GetBlack());
778+
DrawTextUpwards(canvas, 10.0, floor(originTextYPixels - GetTextWidth(settings->yLabel, settings->yLabelLength)/2.0), settings->yLabel, settings->yLabelLength, GetBlack());
779+
DrawText(canvas, floor(originTextXPixels - GetTextWidth(settings->xLabel, settings->xLabelLength)/2.0), yPixelMax + axisLabelPadding, settings->xLabel, settings->xLabelLength, GetBlack());
760780

761781
/* X-grid-markers */
762782
for(i = 0.0; i < xGridPositionsLength; i = i + 1.0){
@@ -899,6 +919,43 @@ if(settings->yAxisLeft){
899919

900920
return success;
901921
}
922+
void ComputeBoundariesBasedOnSettings(ScatterPlotSettings *settings, Rectangle *boundaries){
923+
ScatterPlotSeries *sp;
924+
double plot, xMin, xMax, yMin, yMax;
925+
926+
if(settings->scatterPlotSeriesLength >= 1.0){
927+
xMin = GetMinimum(settings->scatterPlotSeries[0]->xs, settings->scatterPlotSeries[0]->xsLength);
928+
xMax = GetMaximum(settings->scatterPlotSeries[0]->xs, settings->scatterPlotSeries[0]->xsLength);
929+
yMin = GetMinimum(settings->scatterPlotSeries[0]->ys, settings->scatterPlotSeries[0]->ysLength);
930+
yMax = GetMaximum(settings->scatterPlotSeries[0]->ys, settings->scatterPlotSeries[0]->ysLength);
931+
}else{
932+
xMin = -10.0;
933+
xMax = 10.0;
934+
yMin = -10.0;
935+
yMax = 10.0;
936+
}
937+
938+
if( !settings->autoBoundaries ){
939+
xMin = settings->xMin;
940+
xMax = settings->xMax;
941+
yMin = settings->yMin;
942+
yMax = settings->yMax;
943+
}else{
944+
for(plot = 1.0; plot < settings->scatterPlotSeriesLength; plot = plot + 1.0){
945+
sp = settings->scatterPlotSeries[(int)(plot)];
946+
947+
xMin = fmin(xMin, GetMinimum(sp->xs, sp->xsLength));
948+
xMax = fmax(xMax, GetMaximum(sp->xs, sp->xsLength));
949+
yMin = fmin(yMin, GetMinimum(sp->ys, sp->ysLength));
950+
yMax = fmax(yMax, GetMaximum(sp->ys, sp->ysLength));
951+
}
952+
}
953+
954+
boundaries->x1 = xMin;
955+
boundaries->y1 = yMin;
956+
boundaries->x2 = xMax;
957+
boundaries->y2 = yMax;
958+
}
902959
_Bool ScatterPlotFromSettingsValid(ScatterPlotSettings *settings){
903960
_Bool success, found;
904961
ScatterPlotSeries *series;
@@ -1392,7 +1449,6 @@ double RoundToDigits(double element, double digitsAfterPoint){
13921449
return Round(element*pow(10.0, digitsAfterPoint))/pow(10.0, digitsAfterPoint);
13931450
}
13941451
double test(){
1395-
ScatterPlotSettings *scatterPlotSettings;
13961452
double z;
13971453
double *gridlines;
13981454
size_t gridlinesLength;
@@ -1407,8 +1463,6 @@ double test(){
14071463

14081464
imageReference = CreateRGBABitmapImageReference();
14091465

1410-
scatterPlotSettings = GetDefaultScatterPlotSettings();
1411-
14121466
labels = (StringArrayReference *)malloc(sizeof(StringArrayReference));
14131467
labelPriorities = (NumberArrayReference *)malloc(sizeof(NumberArrayReference));
14141468

@@ -1466,8 +1520,151 @@ double test(){
14661520

14671521
imageReference->image = DrawBarPlot(800.0, 600.0, ys, ysLength);
14681522

1523+
TestMapping(failures);
1524+
TestMapping2(failures);
1525+
14691526
return failures->numberValue;
14701527
}
1528+
void TestMapping(NumberReference *failures){
1529+
ScatterPlotSeries *series;
1530+
ScatterPlotSettings *settings;
1531+
RGBABitmapImageReference *imageReference;
1532+
double x1, y1;
1533+
1534+
series = GetDefaultScatterPlotSeriesSettings();
1535+
1536+
series->xs = (double*)malloc(sizeof(double) * (5.0));
1537+
series->xsLength = 5.0;
1538+
series->xs[0] = -2.0;
1539+
series->xs[1] = -1.0;
1540+
series->xs[2] = 0.0;
1541+
series->xs[3] = 1.0;
1542+
series->xs[4] = 2.0;
1543+
series->ys = (double*)malloc(sizeof(double) * (5.0));
1544+
series->ysLength = 5.0;
1545+
series->ys[0] = -2.0;
1546+
series->ys[1] = -1.0;
1547+
series->ys[2] = -2.0;
1548+
series->ys[3] = -1.0;
1549+
series->ys[4] = 2.0;
1550+
series->linearInterpolation = true;
1551+
series->lineType = L"dashed";
1552+
series->lineTypeLength = wcslen(series->lineType);
1553+
series->lineThickness = 2.0;
1554+
series->color = GetGray(0.3);
1555+
1556+
settings = GetDefaultScatterPlotSettings();
1557+
settings->width = 600.0;
1558+
settings->height = 400.0;
1559+
settings->autoBoundaries = true;
1560+
settings->autoPadding = true;
1561+
settings->title = L"x^2 - 2";
1562+
settings->titleLength = wcslen(settings->title);
1563+
settings->xLabel = L"X axis";
1564+
settings->xLabelLength = wcslen(settings->xLabel);
1565+
settings->yLabel = L"Y axis";
1566+
settings->yLabelLength = wcslen(settings->yLabel);
1567+
settings->scatterPlotSeries = (ScatterPlotSeries**)malloc(sizeof(ScatterPlotSeries) * 1.0);
1568+
settings->scatterPlotSeriesLength = 1.0;
1569+
settings->scatterPlotSeries[0] = series;
1570+
1571+
imageReference = CreateRGBABitmapImageReference();
1572+
DrawScatterPlotFromSettings(imageReference, settings);
1573+
1574+
x1 = MapXCoordinateAutoSettings( -1.0, imageReference->image, series->xs, series->xsLength);
1575+
y1 = MapYCoordinateAutoSettings( -1.0, imageReference->image, series->ys, series->ysLength);
1576+
1577+
AssertEquals(x1, 180.0, failures);
1578+
AssertEquals(y1, 280.0, failures);
1579+
}
1580+
void TestMapping2(NumberReference *failures){
1581+
double *xs, *ys, *xs2, *ys2;
1582+
size_t xsLength, ysLength, xs2Length, ys2Length;
1583+
double i, x, y, w, h, xMin, xMax, yMin, yMax;
1584+
RGBABitmapImageReference *canvasReference;
1585+
ScatterPlotSettings *settings;
1586+
double points;
1587+
double x1, y1;
1588+
1589+
points = 300.0;
1590+
w = 600.0*2.0;
1591+
h = 300.0*2.0;
1592+
xMin = 0.0;
1593+
xMax = 150.0;
1594+
yMin = 0.0;
1595+
yMax = 1.0;
1596+
1597+
xs = (double*)malloc(sizeof(double) * (points));
1598+
xsLength = points;
1599+
ys = (double*)malloc(sizeof(double) * (points));
1600+
ysLength = points;
1601+
xs2 = (double*)malloc(sizeof(double) * (points));
1602+
xs2Length = points;
1603+
ys2 = (double*)malloc(sizeof(double) * (points));
1604+
ys2Length = points;
1605+
1606+
for(i = 0.0; i < points; i = i + 1.0){
1607+
x = xMin + (xMax - xMin)/(points - 1.0)*i;
1608+
/* points - 1d is to ensure both extremeties are included. */
1609+
y = x/(x + 7.0);
1610+
1611+
xs[(int)(i)] = x;
1612+
ys[(int)(i)] = y;
1613+
1614+
y = 1.4*x/(x + 7.0)*(1.0 - (atan((x/1.5 - 30.0)/5.0)/1.6 + 1.0)/2.0);
1615+
1616+
xs2[(int)(i)] = x;
1617+
ys2[(int)(i)] = y;
1618+
}
1619+
1620+
settings = GetDefaultScatterPlotSettings();
1621+
1622+
settings->scatterPlotSeries = (ScatterPlotSeries**)malloc(sizeof(ScatterPlotSeries) * 2.0);
1623+
settings->scatterPlotSeriesLength = 2.0;
1624+
settings->scatterPlotSeries[0] = (ScatterPlotSeries *)malloc(sizeof(ScatterPlotSeries));
1625+
settings->scatterPlotSeries[0]->xs = xs;
1626+
settings->scatterPlotSeries[0]->xsLength = xsLength;
1627+
settings->scatterPlotSeries[0]->ys = ys;
1628+
settings->scatterPlotSeries[0]->ysLength = ysLength;
1629+
settings->scatterPlotSeries[0]->linearInterpolation = true;
1630+
settings->scatterPlotSeries[0]->lineType = L"solid";
1631+
settings->scatterPlotSeries[0]->lineTypeLength = wcslen(settings->scatterPlotSeries[0]->lineType);
1632+
settings->scatterPlotSeries[0]->lineThickness = 3.0;
1633+
settings->scatterPlotSeries[0]->color = CreateRGBColor(1.0, 0.0, 0.0);
1634+
settings->scatterPlotSeries[1] = (ScatterPlotSeries *)malloc(sizeof(ScatterPlotSeries));
1635+
settings->scatterPlotSeries[1]->xs = xs2;
1636+
settings->scatterPlotSeries[1]->xsLength = xs2Length;
1637+
settings->scatterPlotSeries[1]->ys = ys2;
1638+
settings->scatterPlotSeries[1]->ysLength = ys2Length;
1639+
settings->scatterPlotSeries[1]->linearInterpolation = true;
1640+
settings->scatterPlotSeries[1]->lineType = L"solid";
1641+
settings->scatterPlotSeries[1]->lineTypeLength = wcslen(settings->scatterPlotSeries[1]->lineType);
1642+
settings->scatterPlotSeries[1]->lineThickness = 3.0;
1643+
settings->scatterPlotSeries[1]->color = CreateRGBColor(0.0, 0.0, 1.0);
1644+
settings->autoBoundaries = false;
1645+
settings->xMin = xMin;
1646+
settings->xMax = xMax;
1647+
settings->yMin = yMin;
1648+
settings->yMax = yMax;
1649+
settings->yLabel = L"";
1650+
settings->yLabelLength = wcslen(settings->yLabel);
1651+
settings->xLabel = L"Features";
1652+
settings->xLabelLength = wcslen(settings->xLabel);
1653+
settings->title = L"";
1654+
settings->titleLength = wcslen(settings->title);
1655+
settings->width = w;
1656+
settings->height = h;
1657+
1658+
canvasReference = CreateRGBABitmapImageReference();
1659+
1660+
DrawScatterPlotFromSettings(canvasReference, settings);
1661+
1662+
x1 = MapXCoordinateBasedOnSettings(27.0, settings);
1663+
y1 = MapYCoordinateBasedOnSettings(1.0, settings);
1664+
1665+
AssertEquals(floor(x1), 292.0, failures);
1666+
AssertEquals(y1, 60.0, failures);
1667+
}
14711668
RGBA *GetBlack(){
14721669
RGBA *black;
14731670
black = (RGBA *)malloc(sizeof(RGBA));

0 commit comments

Comments
 (0)