13 Commits

Author SHA1 Message Date
Martin Preuss
118a8f10cf some markup. 2026-01-10 14:32:12 +01:00
Martin Preuss
fa9656b653 added text. 2026-01-10 14:27:32 +01:00
Martin Preuss
160fea2c0c more text for README.md 2026-01-10 14:26:21 +01:00
Martin Preuss
8b5451c5bd added TODO. 2026-01-05 00:49:06 +01:00
Martin Preuss
1c59e26722 remove unneeded file. 2026-01-05 00:48:09 +01:00
Martin Preuss
c34c5eb51d fixed typos. 2026-01-05 00:43:57 +01:00
Martin Preuss
c06c71b091 added AQDG_Data_DifferenceY() 2026-01-05 00:43:47 +01:00
Martin Preuss
1ac5c428bd another fix for Y ticks. 2026-01-05 00:43:31 +01:00
Martin Preuss
aefbc413a6 another code example 2026-01-04 19:17:49 +01:00
Martin Preuss
9d010c254c added example code. 2026-01-04 19:09:15 +01:00
Martin Preuss
78853bd7be PRepared release 0.1.5. 2026-01-04 15:40:04 +01:00
Martin Preuss
8bafc714c3 another fix for axis ticks. 2026-01-04 15:39:09 +01:00
Martin Preuss
7d139093df fixed axis ticks mainly used for y-axis. 2026-01-04 15:09:10 +01:00
7 changed files with 238 additions and 48 deletions

4
0BUILD
View File

@@ -3,8 +3,8 @@
<gwbuild requiredVersion="5.9.0" > <gwbuild requiredVersion="5.9.0" >
<project name="aqdiagram" version="0.1.4" <project name="aqdiagram" version="0.1.5"
so_current="0" so_age="0" so_revision="4" so_current="0" so_age="0" so_revision="5"
write_config_h="TRUE" write_config_h="TRUE"
> >

View File

@@ -24,8 +24,98 @@ gwbuild -jNN (with NN number of parallel processes, e.g. 4 for quadcore cpu)
sudo gwbuild -i sudo gwbuild -i
``` ```
## Structure of AqDiagram
AqDiagram consists of 4 parts:
- __data__:
Library for data manipulation (accumulate, negate, diff, average, floating average, sums for days and months)
- __draw__:
Library for drawing text and simple figures (points, lines, rectangles), current implementation for libcairo).
- __placement__:
Library for placement of objects in a plane.
- __graph__:
Library for drawing graphs using the other libraries.
## Code Examples ## Code Examples
https://gitea.aqbanking.de/martin/aqdiagram/src/branch/master/src/lib/aqdiagram/libtest.c ### Simple Graph with a Single Curve
```
AQDG_GRAPH *g;
AQDG_GRAPH_DATAPAIR_LIST *dpList;
AQDG_DRAW_CONTEXT *dc;
AQDG_OBJECT *graphObject;
g=AQDG_TimeGraph_new("Title", "Subtitle", "Value", "mm", 0);
/* get data to be shown (insert your function here) */
dpList=CREATE_DATA_FOR_GRAPH();
/* add single curve as line graph */
AQDG_TimeGraph_AddCurve(g, "Testdata", AQDG_GRAPH_TYPE_LINE, dpList);
/* setup ticks for X and Y axis (use auto-calculated upper and lower limit) */
AQDG_TimeGraph_SetupTicks(g, 0, 0.0, 0.0);
/* draw graph as PNG file (here with 800x600 pixels) */
dc=AQDG_Draw_ContextCairo_Png_new("/tmp/testgraph.png", 800, 600);
graphObject=AQDG_GraphWidget_new(NULL, AQDG_OBJECT_OPTIONS_STRETCHX | AQDG_OBJECT_OPTIONS_STRETCHY, dc);
AQDG_Object_SetWidth(graphObject, 800);
AQDG_Object_SetHeight(graphObject, 600);
/* use default pens and fonts */
AQDG_GraphWidget_SetupDefaultPens(graphObject);
AQDG_GraphWidget_SetupDefaultFonts(graphObject);
/* finish creating the PNG file */
AQDG_GraphWidget_FinishWithGraph(graphObject, g);
return 0;
```
### Graph with a Bar Graph and a Derived Line Curve
```
AQDG_GRAPH *g;
AQDG_GRAPH_DATAPAIR_LIST *dpList;
AQDG_GRAPH_DATAPAIR_LIST *derivedDpList;
AQDG_DRAW_CONTEXT *dc;
AQDG_OBJECT *graphObject;
g=AQDG_TimeGraph_new("Title", "Subtitle", "Value", "mm", 0);
/* get data to be shown (insert your function here) */
dpList=CREATE_DATA_FOR_GRAPH();
/* add first curve as bar graph */
AQDG_TimeGraph_AddCurve(g, "Testdata", AQDG_GRAPH_TYPE_BARS, dpList);
/* use a data modification function on initial data (here: accumulate) */
derivedDpList=AQDG_Data_Accumulate(dpList);
/* add 2nd curve with accumulated data as line graph */
AQDG_TimeGraph_AddCurve(g, "Accumulated", AQDG_GRAPH_TYPE_LINE, derivedDpList);
/* setup ticks for X and Y axis (use auto-calculated upper and lower limit) */
AQDG_TimeGraph_SetupTicks(g, 0, 0.0, 0.0);
/* draw graph as PNG file (here with 800x600 pixels) */
dc=AQDG_Draw_ContextCairo_Png_new("/tmp/testgraph.png", 800, 600);
graphObject=AQDG_GraphWidget_new(NULL, AQDG_OBJECT_OPTIONS_STRETCHX | AQDG_OBJECT_OPTIONS_STRETCHY, dc);
AQDG_Object_SetWidth(graphObject, 800);
AQDG_Object_SetHeight(graphObject, 600);
/* use default pens and fonts */
AQDG_GraphWidget_SetupDefaultPens(graphObject);
AQDG_GraphWidget_SetupDefaultFonts(graphObject);
/* finish creating the PNG file */
AQDG_GraphWidget_FinishWithGraph(graphObject, g);
return 0;
```

0
TODO Normal file
View File

View File

@@ -84,3 +84,33 @@ double AQDG_Data_GetAbsMinDiffY(const AQDG_GRAPH_DATAPAIR_LIST *dpList)
AQDG_GRAPH_DATAPAIR_LIST *AQDG_Data_DifferenceY(const AQDG_GRAPH_DATAPAIR_LIST *dpList)
{
if (dpList && AQDG_Graph_DataPair_List_GetCount(dpList)) {
AQDG_GRAPH_DATAPAIR_LIST *newList;
const AQDG_GRAPH_DATAPAIR *dp;
newList=AQDG_Graph_DataPair_List_new();
dp=AQDG_Graph_DataPair_List_First(dpList);
if (dp) {
double lastValue;
lastValue=AQDG_Graph_DataPair_GetValueY(dp);
while(dp) {
AQDG_GRAPH_DATAPAIR *newDp;
double v;
v=AQDG_Graph_DataPair_GetValueY(dp);
newDp=AQDG_Graph_DataPair_dup(dp);
AQDG_Graph_DataPair_SetValueY(newDp, v-lastValue);
AQDG_Graph_DataPair_List_Add(newDp, newList);
lastValue=v;
dp=AQDG_Graph_DataPair_List_Next(dp);
}
return newList;
}
}
return NULL;
}

View File

@@ -20,6 +20,9 @@ extern "C" {
AQDG_API double AQDG_Data_GetAbsMinDiffX(const AQDG_GRAPH_DATAPAIR_LIST *dpList); AQDG_API double AQDG_Data_GetAbsMinDiffX(const AQDG_GRAPH_DATAPAIR_LIST *dpList);
AQDG_API double AQDG_Data_GetAbsMinDiffY(const AQDG_GRAPH_DATAPAIR_LIST *dpList);
AQDG_API AQDG_GRAPH_DATAPAIR_LIST *AQDG_Data_DifferenceY(const AQDG_GRAPH_DATAPAIR_LIST *dpList);

View File

@@ -1 +0,0 @@
Previous af_graphics

View File

@@ -52,6 +52,94 @@
</content> </content>
</inline> </inline>
<inline loc="code">
<content>
static int _genLog10TicksUp($(struct_type) *st, \n
double vStart, \n
double vStep, \n
double vBegin, double vEnd, \n
int level, \n
int precision) \n
{ \n
double vRun; \n
GWEN_BUFFER *dbuf; \n
\n
dbuf=GWEN_Buffer_new(0, 256, 0, 1); \n
vRun=vStart; \n
while(vRun&lt;=vEnd) { \n
if (vRun&gt;=vBegin) { \n
if (!$(struct_prefix)_HasTickValue(st, vRun)) { \n
GWEN_Buffer_AppendArgs(dbuf, "%.*f", precision, vRun); \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), vRun, level, 0, vStep); \n
DBG_INFO(NULL, "Adding tick %d: %s", level, GWEN_Buffer_GetStart(dbuf)); \n
GWEN_Buffer_Reset(dbuf); \n
} \n
} \n
vRun+=vStep; \n
} \n
GWEN_Buffer_free(dbuf); \n
return ($(struct_prefix)_HasAtLeastNLevelTicks(st, level, level?2:4))?1:0; \n
} \n
</content>
</inline>
<inline loc="code">
<content>
static int _genLog10TicksDown($(struct_type) *st, \n
double vStart, \n
double vStep, \n
double vBegin, double vEnd, \n
int level, \n
int precision) \n
{ \n
double vRun; \n
GWEN_BUFFER *dbuf; \n
\n
dbuf=GWEN_Buffer_new(0, 256, 0, 1); \n
vRun=vStart; \n
while(vRun&gt;=vEnd) { \n
if (vRun&lt;=vBegin) { \n
if (!$(struct_prefix)_HasTickValue(st, vRun)) { \n
GWEN_Buffer_AppendArgs(dbuf, "%.*f", precision, vRun); \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), vRun, level, 0, vStep); \n
DBG_INFO(NULL, "Adding tick %d: %s", level, GWEN_Buffer_GetStart(dbuf)); \n
GWEN_Buffer_Reset(dbuf); \n
} \n
} \n
vRun-=vStep; \n
} \n
GWEN_Buffer_free(dbuf); \n
return ($(struct_prefix)_HasAtLeastNLevelTicks(st, level, level?2:4))?1:0; \n
} \n
</content>
</inline>
<inline loc="code">
<content>
static int _genLog10Ticks($(struct_type) *st, \n
double vStart, \n
double vStep, \n
double vMin, double vMax, \n
int level, \n
int precision) \n
{ \n
if (vMin&lt;0.0 && vMax&gt;=0.0) { \n
int rv; \n
\n
rv=_genLog10TicksUp(st, 0.0, vStep, 0.0, vMax, level, precision); \n
rv|=_genLog10TicksDown(st, 0.0, vStep, 0.0, vMin, level, precision); \n
return rv; \n
} \n
else if (vMin&lt;0.0 && vMax&lt;=0.0) \n
return _genLog10TicksDown(st, vStart, vStep, vMax, vMin, level, precision); \n
else \n
return _genLog10TicksUp(st, vStart, vStep, vMin, vMax, level, precision); \n
} \n
</content>
</inline>
<inline loc="end" access="public"> <inline loc="end" access="public">
<content> <content>
@@ -65,68 +153,48 @@
{ \n { \n
double absMaxValue; \n double absMaxValue; \n
double v; \n double v; \n
double vRun; \n double vMin; \n
double startValue; \n double vMax; \n
GWEN_BUFFER *dbuf; \n double vStart; \n
int nextLevel=0; \n int nextLevel=0; \n
\n \n
absMaxValue=abs(st-&gt;minValue); \n vMin=st-&gt;minValue; \n
v=abs(st-&gt;maxValue); \n vMax=st-&gt;maxValue; \n
absMaxValue=abs(vMin); \n
v=abs(vMax); \n
absMaxValue=(v&gt;absMaxValue)?v:absMaxValue; \n absMaxValue=(v&gt;absMaxValue)?v:absMaxValue; \n
\n \n
dbuf=GWEN_Buffer_new(0, 64, 0, 1); \n
if (absMaxValue==0.0) \n if (absMaxValue==0.0) \n
absMaxValue=1.0; \n absMaxValue=1.0; \n
v=pow(10, floor(log10(absMaxValue))); \n v=pow(10, floor(log10(absMaxValue))); \n
\n \n
startValue=v; \n vStart=v; \n
if ((st-&gt;minValue)&lt;startValue) \n if (vMin&lt;vStart) \n
startValue=-startValue; \n vStart=-vStart; \n
\n
for(;;) { \n
int rv; \n
\n \n
while(v&gt;=0.0) { \n
DBG_INFO(NULL, "Handling level %d (%.2f)", nextLevel, v); \n DBG_INFO(NULL, "Handling level %d (%.2f)", nextLevel, v); \n
if (nextLevel&gt;=3) \n if (nextLevel&gt;=3) \n
break; \n break; \n
vRun=startValue; \n rv=_genLog10Ticks(st, vStart, v, vMin, vMax, nextLevel, st-&gt;precision); \n
while(vRun&lt;=(st-&gt;maxValue)) { \n if (rv) \n
if (vRun&gt;=(st-&gt;minValue)) { \n nextLevel++; \n
if (!$(struct_prefix)_HasTickValue(st, vRun)) { \n else \n
GWEN_Buffer_AppendArgs(dbuf, "%.*f", st-&gt;precision, vRun); \n $(struct_prefix)_RemoveLevelTicks(st, nextLevel); \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), vRun, nextLevel, 0, v); \n
DBG_INFO(NULL, "Adding tick %d: %s", nextLevel, GWEN_Buffer_GetStart(dbuf)); \n
GWEN_Buffer_Reset(dbuf); \n
} \n
} \n
vRun+=v; \n
} \n
v/=2.0; \n v/=2.0; \n
if ($(struct_prefix)_HasAtLeastNLevelTicks(st, nextLevel, nextLevel?1:4)) \n
nextLevel++; \n
else \n
$(struct_prefix)_RemoveLevelTicks(st, nextLevel); \n
\n \n
DBG_INFO(NULL, "Handling level %d (%.2f)", nextLevel, v); \n
if (nextLevel&gt;=3) \n if (nextLevel&gt;=3) \n
break; \n break; \n
vRun=startValue; \n DBG_INFO(NULL, "Handling level %d (%.2f)", nextLevel, v); \n
while(vRun&lt;=(st-&gt;maxValue)) { \n rv=_genLog10Ticks(st, vStart, v, vMin, vMax, nextLevel, st-&gt;precision); \n
if (vRun&gt;=(st-&gt;minValue)) { \n if (rv) \n
if (!$(struct_prefix)_HasTickValue(st, vRun)) { \n
GWEN_Buffer_AppendArgs(dbuf, "%.*f", st-&gt;precision, vRun); \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), vRun, nextLevel, 0, v); \n
DBG_INFO(NULL, "Adding tick %d: %s", nextLevel, GWEN_Buffer_GetStart(dbuf)); \n
GWEN_Buffer_Reset(dbuf); \n
} \n
} \n
vRun+=v; \n
} \n
v/=5.0; \n
if ($(struct_prefix)_HasAtLeastNLevelTicks(st, nextLevel, nextLevel?1:4)) \n
nextLevel++; \n nextLevel++; \n
else \n else \n
$(struct_prefix)_RemoveLevelTicks(st, nextLevel); \n $(struct_prefix)_RemoveLevelTicks(st, nextLevel); \n
} /* while */ \n v/=5.0; \n
GWEN_Buffer_free(dbuf); \n } /* for */ \n
} \n } \n
</content> </content>
</inline> </inline>