Skip to content

Commit 5f697e1

Browse files
committed
fix #535, allow transparency in plots
1 parent 7594a99 commit 5f697e1

10 files changed

Lines changed: 274 additions & 81 deletions

QtSLiM/QtSLiMGraphView.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,7 @@ void QtSLiMGraphView::drawLegend(QPainter &painter, QRectF legendRect)
10511051
{
10521052
drawPointSymbol(painter, graphicsBox.center().x(), graphicsBox.center().y(),
10531053
legendEntry.point_symbol, legendEntry.point_color, legendEntry.point_border,
1054-
legendEntry.point_lwd, legendEntry.point_size);
1054+
/* alpha */ 1.0, legendEntry.point_lwd, legendEntry.point_size);
10551055
break;
10561056
}
10571057
default: break;
@@ -1866,10 +1866,16 @@ QtSLiMLegendSpec QtSLiMGraphView::mutationTypeLegendKey(void)
18661866
return legend_key;
18671867
}
18681868

1869-
void QtSLiMGraphView::drawPointSymbol(QPainter &painter, double x, double y, int symbol, QColor symbolColor, QColor borderColor, double lineWidth, double size)
1869+
void QtSLiMGraphView::drawPointSymbol(QPainter &painter, double x, double y, int symbol, QColor symbolColor, QColor borderColor, double alpha, double lineWidth, double size)
18701870
{
18711871
size = size * 3.5; // this scales what size=1 looks like
18721872

1873+
if (alpha != 1.0)
1874+
{
1875+
symbolColor.setAlphaF(alpha);
1876+
borderColor.setAlphaF(alpha);
1877+
}
1878+
18731879
switch (symbol)
18741880
{
18751881
case 0: // square outline

QtSLiM/QtSLiMGraphView.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ public slots:
255255
protected:
256256
int lineCountForLegend(QtSLiMLegendSpec &legend);
257257
double graphicsWidthForLegend(QtSLiMLegendSpec &legend, double legendLineHeight);
258-
void drawPointSymbol(QPainter &painter, double x, double y, int symbol, QColor symbolColor, QColor borderColor, double lineWidth, double size);
258+
void drawPointSymbol(QPainter &painter, double x, double y, int symbol, QColor symbolColor, QColor borderColor, double alpha, double lineWidth, double size);
259259

260260
private:
261261
virtual void paintEvent(QPaintEvent *p_paintEvent) override;

QtSLiM/QtSLiMGraphView_CustomPlot.cpp

Lines changed: 97 additions & 30 deletions
Large diffs are not rendered by default.

QtSLiM/QtSLiMGraphView_CustomPlot.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,16 @@ class QtSLiMGraphView_CustomPlot : public QtSLiMGraphView
6565

6666
void addABLineData(double *a_values, double *b_values,
6767
double *h_values, double *v_values, int data_count,
68-
std::vector<QColor> *color, std::vector<double> *lwd);
68+
std::vector<QColor> *color, std::vector<double> *alpha,
69+
std::vector<double> *lwd);
6970
void addLineData(double *x_values, double *y_values, int data_count,
70-
std::vector<QColor> *color, std::vector<double> *lwd);
71+
std::vector<QColor> *color, std::vector<double> *alpha,
72+
std::vector<double> *lwd);
7173
void addPointData(double *x_values, double *y_values, int data_count,
7274
std::vector<int> *symbol, std::vector<QColor> *color, std::vector<QColor> *border,
73-
std::vector<double> *lwd, std::vector<double> *size);
75+
std::vector<double> *alpha, std::vector<double> *lwd, std::vector<double> *size);
7476
void addTextData(double *x_values, double *y_values, std::vector<QString> *labels, int data_count,
75-
std::vector<QColor> *color, std::vector<double> *size, double *adj);
77+
std::vector<QColor> *color, std::vector<double> *alpha, std::vector<double> *size, double *adj);
7678

7779
void addLegend(QtSLiM_LegendPosition position, int inset, double labelSize, double lineHeight,
7880
double graphicsWidth, double exteriorMargin, double interiorMargin);
@@ -109,6 +111,7 @@ public slots:
109111
std::vector<std::vector<int> *> symbol_; // one symbol per point, OR one symbol for all points
110112
std::vector<std::vector<QColor> *> color_; // one color per point, OR one color for all points
111113
std::vector<std::vector<QColor> *> border_; // one border color per point, OR one for all points
114+
std::vector<std::vector<double> *> alpha_; // one alpha per point, OR one alpha for all points
112115
std::vector<std::vector<double> *> line_width_; // one lwd per point, OR one lwd for all points
113116
std::vector<std::vector<double> *> size_; // one size per point, OR one size for all points
114117
std::vector<double> xadj_; // one xadj for all points

QtSLiM/QtSLiMWindow.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5005,10 +5005,13 @@ void QtSLiMWindow::plotLogFileData_1D(QString title, QString y_title, double *y_
50055005
std::vector<QColor> *color = new std::vector<QColor>;
50065006
color->emplace_back(255, 0, 0, 255);
50075007

5008+
std::vector<double> *alpha = new std::vector<double>;
5009+
alpha->push_back(1.0);
5010+
50085011
std::vector<double> *lwd = new std::vector<double>;
50095012
lwd->push_back(1.5);
50105013

5011-
plot->addLineData(x_values, y_values, data_count, color, lwd); // takes buffers from us
5014+
plot->addLineData(x_values, y_values, data_count, color, alpha, lwd); // takes buffers from us
50125015
}
50135016

50145017
void QtSLiMWindow::plotLogFileData_2D(QString title, QString x_title, QString y_title, double *x_values, double *y_values, int data_count, bool makeScatterPlot)
@@ -5019,6 +5022,9 @@ void QtSLiMWindow::plotLogFileData_2D(QString title, QString x_title, QString y_
50195022
std::vector<QColor> *color = new std::vector<QColor>;
50205023
color->emplace_back(0, 0, 0, 255);
50215024

5025+
std::vector<double> *alpha = new std::vector<double>;
5026+
alpha->push_back(1.0);
5027+
50225028
std::vector<double> *lwd = new std::vector<double>;
50235029
lwd->push_back(1.0);
50245030

@@ -5033,11 +5039,11 @@ void QtSLiMWindow::plotLogFileData_2D(QString title, QString x_title, QString y_
50335039
std::vector<double> *size = new std::vector<double>;
50345040
size->push_back(0.5);
50355041

5036-
plot->addPointData(x_values, y_values, data_count, symbol, color, border, lwd, size); // takes buffers from us
5042+
plot->addPointData(x_values, y_values, data_count, symbol, color, border, alpha, lwd, size); // takes buffers from us
50375043
}
50385044
else
50395045
{
5040-
plot->addLineData(x_values, y_values, data_count, color, lwd); // takes buffers from us
5046+
plot->addLineData(x_values, y_values, data_count, color, alpha, lwd); // takes buffers from us
50415047
}
50425048
}
50435049

QtSLiM/QtSLiM_Plot.cpp

Lines changed: 77 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ EidosValue_SP Plot::ExecuteInstanceMethod(EidosGlobalStringID p_method_id, const
113113
}
114114
}
115115

116-
// ********************* – (void)abline([Nif a = NULL], [Nif b = NULL], [Nif h = NULL], [Nif v = NULL], [string color = "red"], [numeric lwd = 1.0])
116+
// ********************* – (void)abline([Nif a = NULL], [Nif b = NULL], [Nif h = NULL], [Nif v = NULL], [string color = "red"], [numeric lwd = 1.0], [float alpha = 1.0])
117117
//
118118
EidosValue_SP Plot::ExecuteMethod_abline(EidosGlobalStringID p_method_id, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter)
119119
{
@@ -124,6 +124,7 @@ EidosValue_SP Plot::ExecuteMethod_abline(EidosGlobalStringID p_method_id, const
124124
EidosValue *v_value = p_arguments[3].get();
125125
EidosValue *color_value = p_arguments[4].get();
126126
EidosValue *lwd_value = p_arguments[5].get();
127+
EidosValue *alpha_value = p_arguments[6].get();
127128
double *a = nullptr, *b = nullptr, *h = nullptr, *v = nullptr;
128129
int line_count;
129130

@@ -225,7 +226,24 @@ EidosValue_SP Plot::ExecuteMethod_abline(EidosGlobalStringID p_method_id, const
225226
lwds->push_back(lwd);
226227
}
227228

228-
plotview_->addABLineData(a, b, h, v, line_count, colors, lwds); // takes ownership of buffers
229+
// alpha
230+
std::vector<double> *alphas = new std::vector<double>;
231+
int alpha_count = alpha_value->Count();
232+
233+
if ((alpha_count != 1) && (alpha_count != line_count))
234+
EIDOS_TERMINATION << "ERROR (Plot::ExecuteMethod_abline): abline() requires alpha to match the number of lines, or be singleton." << EidosTerminate();
235+
236+
for (int index = 0; index < alpha_count; ++index)
237+
{
238+
double alpha = alpha_value->FloatAtIndex_NOCAST(index, nullptr);
239+
240+
if ((alpha < 0.0) || (alpha > 1.0))
241+
EIDOS_TERMINATION << "ERROR (Plot::ExecuteMethod_abline): abline() requires the elements of alpha to be in [0, 1]." << EidosTerminate(nullptr);
242+
243+
alphas->push_back(alpha);
244+
}
245+
246+
plotview_->addABLineData(a, b, h, v, line_count, colors, alphas, lwds); // takes ownership of buffers
229247

230248
return gStaticEidosValueVOID;
231249
}
@@ -553,7 +571,7 @@ EidosValue_SP Plot::ExecuteMethod_legendSwatchEntry(EidosGlobalStringID p_method
553571
return gStaticEidosValueVOID;
554572
}
555573

556-
// ********************* – (void)lines(numeric x, numeric y, [string$ color = "red"], [numeric$ lwd = 1.0])
574+
// ********************* – (void)lines(numeric x, numeric y, [string$ color = "red"], [numeric$ lwd = 1.0], [float$ alpha = 1.0])
557575
//
558576
EidosValue_SP Plot::ExecuteMethod_lines(EidosGlobalStringID p_method_id, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter)
559577
{
@@ -562,6 +580,7 @@ EidosValue_SP Plot::ExecuteMethod_lines(EidosGlobalStringID p_method_id, const s
562580
EidosValue *y_value = p_arguments[1].get();
563581
EidosValue *color_value = p_arguments[2].get();
564582
EidosValue *lwd_value = p_arguments[3].get();
583+
EidosValue *alpha_value = p_arguments[4].get();
565584

566585
// x and y
567586
int xcount = x_value->Count();
@@ -620,12 +639,22 @@ EidosValue_SP Plot::ExecuteMethod_lines(EidosGlobalStringID p_method_id, const s
620639

621640
lineWidths->push_back(lwd);
622641

623-
plotview_->addLineData(x, y, xcount, colors, lineWidths); // takes ownership of buffers
642+
// alpha
643+
double alpha = alpha_value->FloatAtIndex_NOCAST(0, nullptr);
644+
645+
if ((alpha < 0.0) || (alpha > 1.0))
646+
EIDOS_TERMINATION << "ERROR (Plot::ExecuteMethod_lines): lines() requires the line width alpha to be in [0, 1]." << EidosTerminate(nullptr);
647+
648+
std::vector<double> *lineAlphas = new std::vector<double>; // we only take a singleton alpha, but the API expects a buffer
649+
650+
lineAlphas->push_back(alpha);
651+
652+
plotview_->addLineData(x, y, xcount, colors, lineAlphas, lineWidths); // takes ownership of buffers
624653

625654
return gStaticEidosValueVOID;
626655
}
627656

628-
// ********************* – (void)points(numeric x, numeric y, [integer symbol = 0], [string color = "red"], [string border = "black"], [numeric lwd = 1.0], [numeric size = 1.0])
657+
// ********************* – (void)points(numeric x, numeric y, [integer symbol = 0], [string color = "red"], [string border = "black"], [numeric lwd = 1.0], [numeric size = 1.0], [float alpha = 1.0])
629658
//
630659
EidosValue_SP Plot::ExecuteMethod_points(EidosGlobalStringID p_method_id, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter)
631660
{
@@ -637,6 +666,7 @@ EidosValue_SP Plot::ExecuteMethod_points(EidosGlobalStringID p_method_id, const
637666
EidosValue *border_value = p_arguments[4].get();
638667
EidosValue *lwd_value = p_arguments[5].get();
639668
EidosValue *size_value = p_arguments[6].get();
669+
EidosValue *alpha_value = p_arguments[7].get();
640670

641671
// x and y
642672
int xcount = x_value->Count();
@@ -760,12 +790,29 @@ EidosValue_SP Plot::ExecuteMethod_points(EidosGlobalStringID p_method_id, const
760790
sizes->push_back(size);
761791
}
762792

763-
plotview_->addPointData(x, y, xcount, symbols, colors, borders, lwds, sizes); // takes ownership of buffers
793+
// alpha
794+
std::vector<double> *alphas = new std::vector<double>;
795+
int alpha_count = alpha_value->Count();
796+
797+
if ((alpha_count != 1) && (alpha_count != xcount))
798+
EIDOS_TERMINATION << "ERROR (Plot::ExecuteMethod_points): points() requires alpha to match the length of x and y, or be singleton." << EidosTerminate();
799+
800+
for (int index = 0; index < alpha_count; ++index)
801+
{
802+
double alpha = alpha_value->FloatAtIndex_NOCAST(index, nullptr);
803+
804+
if ((alpha < 0.0) || (alpha > 1.0))
805+
EIDOS_TERMINATION << "ERROR (Plot::ExecuteMethod_points): points() requires the elements of alpha to be in [0, 1]." << EidosTerminate(nullptr);
806+
807+
alphas->push_back(alpha);
808+
}
809+
810+
plotview_->addPointData(x, y, xcount, symbols, colors, borders, alphas, lwds, sizes); // takes ownership of buffers
764811

765812
return gStaticEidosValueVOID;
766813
}
767814

768-
// ********************* – (void)text(numeric x, numeric y, string labels, [string color = "black"], [numeric size = 10.0], [Nif adj = NULL])
815+
// ********************* – (void)text(numeric x, numeric y, string labels, [string color = "black"], [numeric size = 10.0], [Nif adj = NULL], [float alpha = 1.0])
769816
//
770817
EidosValue_SP Plot::ExecuteMethod_text(EidosGlobalStringID p_method_id, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter)
771818
{
@@ -776,6 +823,7 @@ EidosValue_SP Plot::ExecuteMethod_text(EidosGlobalStringID p_method_id, const st
776823
EidosValue *color_value = p_arguments[3].get();
777824
EidosValue *size_value = p_arguments[4].get();
778825
EidosValue *adj_value = p_arguments[5].get();
826+
EidosValue *alpha_value = p_arguments[6].get();
779827

780828
// x and y
781829
int xcount = x_value->Count();
@@ -868,7 +916,24 @@ EidosValue_SP Plot::ExecuteMethod_text(EidosGlobalStringID p_method_id, const st
868916
adj[1] = adj_value->NumericAtIndex_NOCAST(1, nullptr);
869917
}
870918

871-
plotview_->addTextData(x, y, labels, xcount, colors, sizes, adj); // takes ownership of buffers
919+
// alpha
920+
std::vector<double> *alphas = new std::vector<double>;
921+
int alpha_count = alpha_value->Count();
922+
923+
if ((alpha_count != 1) && (alpha_count != xcount))
924+
EIDOS_TERMINATION << "ERROR (Plot::ExecuteMethod_text): text() requires alpha to match the length of x and y, or be singleton." << EidosTerminate();
925+
926+
for (int index = 0; index < alpha_count; ++index)
927+
{
928+
double alpha = alpha_value->FloatAtIndex_NOCAST(index, nullptr);
929+
930+
if ((alpha < 0.0) || (alpha > 1.0))
931+
EIDOS_TERMINATION << "ERROR (Plot::ExecuteMethod_text): text() requires the elements of alpha to be in [0, 1]." << EidosTerminate(nullptr);
932+
933+
alphas->push_back(alpha);
934+
}
935+
936+
plotview_->addTextData(x, y, labels, xcount, colors, alphas, sizes, adj); // takes ownership of buffers
872937

873938
return gStaticEidosValueVOID;
874939
}
@@ -933,7 +998,7 @@ const std::vector<EidosMethodSignature_CSP> *Plot_Class::Methods(void) const
933998
->AddNumeric_ON("a", gStaticEidosValueNULL)->AddNumeric_ON("b", gStaticEidosValueNULL)
934999
->AddNumeric_ON("h", gStaticEidosValueNULL)->AddNumeric_ON("v", gStaticEidosValueNULL)
9351000
->AddString_O("color", EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String("red")))
936-
->AddNumeric_O("lwd", gStaticEidosValue_Float1)));
1001+
->AddNumeric_O("lwd", gStaticEidosValue_Float1)->AddFloat_O("alpha", gStaticEidosValue_Float1)));
9371002
methods->emplace_back(static_cast<EidosInstanceMethodSignature *>((new EidosInstanceMethodSignature(gStr_addLegend, kEidosValueMaskVOID))
9381003
->AddString_OSN("position", gStaticEidosValueNULL)->AddInt_OSN("inset", gStaticEidosValueNULL)
9391004
->AddNumeric_OSN("labelSize", gStaticEidosValueNULL)->AddNumeric_OSN("lineHeight", gStaticEidosValueNULL)
@@ -954,17 +1019,17 @@ const std::vector<EidosMethodSignature_CSP> *Plot_Class::Methods(void) const
9541019
->AddString_S("label")->AddString_OS("color", EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String("red")))));
9551020
methods->emplace_back(static_cast<EidosInstanceMethodSignature *>((new EidosInstanceMethodSignature(gStr_lines, kEidosValueMaskVOID))
9561021
->AddNumeric("x")->AddNumeric("y")->AddString_OS("color", EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String("red")))
957-
->AddNumeric_OS("lwd", gStaticEidosValue_Float1)));
1022+
->AddNumeric_OS("lwd", gStaticEidosValue_Float1)->AddFloat_OS("alpha", gStaticEidosValue_Float1)));
9581023
methods->emplace_back(static_cast<EidosInstanceMethodSignature *>((new EidosInstanceMethodSignature(gStr_points, kEidosValueMaskVOID))
9591024
->AddNumeric("x")->AddNumeric("y")->AddInt_O("symbol", gStaticEidosValue_Integer0)
9601025
->AddString_O("color", EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String("red")))
9611026
->AddString_O("border", EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String("black")))
962-
->AddNumeric_O("lwd", gStaticEidosValue_Float1)->AddNumeric_O("size", gStaticEidosValue_Float1)));
1027+
->AddNumeric_O("lwd", gStaticEidosValue_Float1)->AddNumeric_O("size", gStaticEidosValue_Float1)->AddFloat_O("alpha", gStaticEidosValue_Float1)));
9631028
methods->emplace_back(static_cast<EidosInstanceMethodSignature *>((new EidosInstanceMethodSignature(gStr_text, kEidosValueMaskVOID))
9641029
->AddNumeric("x")->AddNumeric("y")->AddString("labels")
9651030
->AddString_O("color", EidosValue_String_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_String("black")))
9661031
->AddNumeric_O("size", EidosValue_Float_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Float(10)))
967-
->AddNumeric_ON("adj", gStaticEidosValueNULL)));
1032+
->AddNumeric_ON("adj", gStaticEidosValueNULL)->AddFloat_O("alpha", gStaticEidosValue_Float1)));
9681033
methods->emplace_back(static_cast<EidosInstanceMethodSignature *>((new EidosInstanceMethodSignature(gEidosStr_write, kEidosValueMaskVOID))
9691034
->AddString_S(gEidosStr_filePath)));
9701035

0 commit comments

Comments
 (0)