improved y axis tick generation and labeling.

This commit is contained in:
Martin Preuss
2025-10-22 22:12:41 +02:00
parent 855588a2fc
commit a5c611b140
4 changed files with 176 additions and 92 deletions

View File

@@ -29,13 +29,13 @@
<inlines> <inlines>
<inline loc="end" access="public"> <inline loc="end" access="public">
<content> <content>
$(api) void $(struct_prefix)_AddNewTick($(struct_type) *st, const char *label, double v, int lvl, uint32_t flags); $(api) void $(struct_prefix)_AddNewTick($(struct_type) *st, const char *label, double v, int lvl, uint32_t flags, double dist);
</content> </content>
</inline> </inline>
<inline loc="code"> <inline loc="code">
<content> <content>
void $(struct_prefix)_AddNewTick($(struct_type) *st, const char *label, double v, int lvl, uint32_t flags) \n void $(struct_prefix)_AddNewTick($(struct_type) *st, const char *label, double v, int lvl, uint32_t flags, double dist) \n
{ \n { \n
AQDG_GRAPH_TICK *tick; \n AQDG_GRAPH_TICK *tick; \n
\n \n
@@ -44,6 +44,7 @@
AQDG_Graph_Tick_SetValue(tick, v); \n AQDG_Graph_Tick_SetValue(tick, v); \n
AQDG_Graph_Tick_SetLevel(tick, lvl); \n AQDG_Graph_Tick_SetLevel(tick, lvl); \n
AQDG_Graph_Tick_SetFlags(tick, flags); \n AQDG_Graph_Tick_SetFlags(tick, flags); \n
AQDG_Graph_Tick_SetLevelDist(tick, dist); \n
if (st-&gt;tickList==NULL) \n if (st-&gt;tickList==NULL) \n
st-&gt;tickList=AQDG_Graph_Tick_List_new(); \n st-&gt;tickList=AQDG_Graph_Tick_List_new(); \n
AQDG_Graph_Tick_List_Add(tick, st-&gt;tickList); \n AQDG_Graph_Tick_List_Add(tick, st-&gt;tickList); \n
@@ -60,77 +61,73 @@
<inline loc="code"> <inline loc="code">
<content> <content>
void $(struct_prefix)_GenLog10Ticks($(struct_type) *st) \n void $(struct_prefix)_GenLog10Ticks($(struct_type) *st) \n
{ \n { \n
double absMaxValue; \n double absMaxValue; \n
double v; \n double v; \n
double vRun; \n double vRun; \n
double startValue; \n double startValue; \n
GWEN_BUFFER *dbuf; \n GWEN_BUFFER *dbuf; \n
int nextLevel=0; \n int nextLevel=0; \n
\n \n
absMaxValue=abs(st-&gt;minValue); \n absMaxValue=abs(st-&gt;minValue); \n
v=abs(st-&gt;maxValue); \n v=abs(st-&gt;maxValue); \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 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 startValue=v; \n
if ((st-&gt;minValue)&lt;startValue) \n if ((st-&gt;minValue)&lt;startValue) \n
startValue=-startValue; \n startValue=-startValue; \n
\n \n
vRun=startValue; \n while(v&gt;=0.0) { \n
DBG_ERROR(NULL, "vRun=%.2f, v=%.2f, vMin=%.2f, vMax=%.2f", vRun, v, st-&gt;minValue, st-&gt;maxValue); \n DBG_ERROR(NULL, "Handling level %d (%.2f)", nextLevel, v); \n
while(vRun&lt;=(st-&gt;maxValue)) { \n if (nextLevel&gt;=2) \n
if (vRun&gt;=(st-&gt;minValue)) { \n break; \n
if (!$(struct_prefix)_HasTickValue(st, vRun)) { \n vRun=startValue; \n
GWEN_Buffer_AppendArgs(dbuf, "%.*f", st-&gt;precision, vRun); \n while(vRun&lt;=(st-&gt;maxValue)) { \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), vRun, nextLevel, 0); \n if (vRun&gt;=(st-&gt;minValue)) { \n
GWEN_Buffer_Reset(dbuf); \n if (!$(struct_prefix)_HasTickValue(st, vRun)) { \n
} \n GWEN_Buffer_AppendArgs(dbuf, "%.*f", st-&gt;precision, vRun); \n
} \n $(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), vRun, nextLevel, 0, v); \n
vRun+=v; \n DBG_ERROR(NULL, "Adding tick %d: %s", nextLevel, GWEN_Buffer_GetStart(dbuf)); \n
} \n GWEN_Buffer_Reset(dbuf); \n
if ($(struct_prefix)_HasLevelTicks(st, nextLevel)) \n } \n
nextLevel++; \n } \n
\n vRun+=v; \n
vRun=startValue; \n } \n
v/=2.0; \n v/=2.0; \n
DBG_ERROR(NULL, "vRun=%.2f, v=%.2f, vMin=%.2f, vMax=%.2f", vRun, v, st-&gt;minValue, st-&gt;maxValue); \n if ($(struct_prefix)_HasAtLeastNLevelTicks(st, nextLevel, nextLevel?1:2)) \n
while(vRun&lt;=(st-&gt;maxValue)) { \n nextLevel++; \n
if (vRun&gt;=(st-&gt;minValue)) { \n else \n
if (!$(struct_prefix)_HasTickValue(st, vRun)) { \n $(struct_prefix)_RemoveLevelTicks(st, nextLevel); \n
GWEN_Buffer_AppendArgs(dbuf, "%.*f", st-&gt;precision, vRun); \n \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), vRun, nextLevel, 0); \n DBG_ERROR(NULL, "Handling level %d (%.2f)", nextLevel, v); \n
GWEN_Buffer_Reset(dbuf); \n if (nextLevel&gt;=2) \n
} \n break; \n
} \n vRun=startValue; \n
vRun+=v; \n while(vRun&lt;=(st-&gt;maxValue)) { \n
} \n if (vRun&gt;=(st-&gt;minValue)) { \n
if ($(struct_prefix)_HasLevelTicks(st, nextLevel)) \n if (!$(struct_prefix)_HasTickValue(st, vRun)) { \n
nextLevel++; \n GWEN_Buffer_AppendArgs(dbuf, "%.*f", st-&gt;precision, vRun); \n
\n $(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), vRun, nextLevel, 0, v); \n
vRun=startValue; \n DBG_ERROR(NULL, "Adding tick %d: %s", nextLevel, GWEN_Buffer_GetStart(dbuf)); \n
v/=5.0; \n GWEN_Buffer_Reset(dbuf); \n
DBG_ERROR(NULL, "vRun=%.2f, v=%.2f, vMin=%.2f, vMax=%.2f", vRun, v, st-&gt;minValue, st-&gt;maxValue); \n } \n
while(vRun&lt;=(st-&gt;maxValue)) { \n } \n
if (vRun&gt;=(st-&gt;minValue)) { \n vRun+=v; \n
if (!$(struct_prefix)_HasTickValue(st, vRun)) { \n } \n
GWEN_Buffer_AppendArgs(dbuf, "%.*f", st-&gt;precision, vRun); \n v/=5.0; \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), vRun, nextLevel, 0); \n if ($(struct_prefix)_HasAtLeastNLevelTicks(st, nextLevel, nextLevel?1:2)) \n
GWEN_Buffer_Reset(dbuf); \n nextLevel++; \n
} \n else \n
} \n $(struct_prefix)_RemoveLevelTicks(st, nextLevel); \n
vRun+=v; \n } /* while */ \n
} \n GWEN_Buffer_free(dbuf); \n
if ($(struct_prefix)_HasLevelTicks(st, nextLevel)) \n } \n
nextLevel++; \n
\n
GWEN_Buffer_free(dbuf); \n
} \n
</content> </content>
</inline> </inline>
@@ -161,20 +158,24 @@
<inline loc="end" access="public"> <inline loc="end" access="public">
<content> <content>
$(api) int $(struct_prefix)_HasLevelTicks(const $(struct_type) *st, int level); $(api) int $(struct_prefix)_HasAtLeastNLevelTicks(const $(struct_type) *st, int level, int min);
</content> </content>
</inline> </inline>
<inline loc="code"> <inline loc="code">
<content> <content>
int $(struct_prefix)_HasLevelTicks(const $(struct_type) *st, int level) \n int $(struct_prefix)_HasAtLeastNLevelTicks(const $(struct_type) *st, int level, int min) \n
{ \n { \n
const AQDG_GRAPH_TICK *tick; \n const AQDG_GRAPH_TICK *tick; \n
int cnt=0; \n
\n \n
tick=AQDG_Graph_Tick_List_First(st-&gt;tickList); \n tick=AQDG_Graph_Tick_List_First(st-&gt;tickList); \n
while(tick) { \n while(tick) { \n
if (AQDG_Graph_Tick_GetLevel(tick)==level) \n if (AQDG_Graph_Tick_GetLevel(tick)==level) { \n
return 1; \n cnt++; \n
if (cnt>=min) \n
return 1; \n
}
tick=AQDG_Graph_Tick_List_Next(tick); \n tick=AQDG_Graph_Tick_List_Next(tick); \n
} \n } \n
return 0; \n return 0; \n
@@ -183,6 +184,35 @@
</inline> </inline>
<inline loc="end" access="public">
<content>
$(api) void $(struct_prefix)_RemoveLevelTicks($(struct_type) *st, int level);
</content>
</inline>
<inline loc="code">
<content>
void $(struct_prefix)_RemoveLevelTicks($(struct_type) *st, int level) \n
{ \n
AQDG_GRAPH_TICK *tick; \n
\n
tick=AQDG_Graph_Tick_List_First(st-&gt;tickList); \n
while(tick) { \n
AQDG_GRAPH_TICK *nextTick; \n
\n
nextTick=AQDG_Graph_Tick_List_Next(tick); \n
if (AQDG_Graph_Tick_GetLevel(tick)==level) { \n
AQDG_Graph_Tick_List_Del(tick); \n
AQDG_Graph_Tick_free(tick); \n
} \n
tick=nextTick; \n
} \n
} \n
</content>
</inline>
<inline loc="end" access="public"> <inline loc="end" access="public">
<content> <content>
$(api) void $(struct_prefix)_GenHourTicks($(struct_type) *st, int lvl, int hours); $(api) void $(struct_prefix)_GenHourTicks($(struct_type) *st, int lvl, int hours);
@@ -198,7 +228,9 @@
GWEN_BUFFER *dbuf; \n GWEN_BUFFER *dbuf; \n
GWEN_TIMESTAMP *ts; \n GWEN_TIMESTAMP *ts; \n
int h; \n int h; \n
int addSecs; \n
\n \n
addSecs=hours*60*60; \n
maxValue=st-&gt;maxValue; \n maxValue=st-&gt;maxValue; \n
minValue=st-&gt;minValue; \n minValue=st-&gt;minValue; \n
ts=GWEN_Timestamp_fromLocalTime(minValue); \n ts=GWEN_Timestamp_fromLocalTime(minValue); \n
@@ -216,10 +248,10 @@
GWEN_Timestamp_GetHour(ts), \n GWEN_Timestamp_GetHour(ts), \n
GWEN_Timestamp_GetMinute(ts)); \n GWEN_Timestamp_GetMinute(ts)); \n
if (!$(struct_prefix)_HasTickValue(st, v)) \n if (!$(struct_prefix)_HasTickValue(st, v)) \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), v, lvl, 0); \n $(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), v, lvl, 0, (double) addSecs); \n
GWEN_Buffer_Reset(dbuf); \n GWEN_Buffer_Reset(dbuf); \n
} \n } \n
GWEN_Timestamp_AddSeconds(ts, hours*60*60); \n GWEN_Timestamp_AddSeconds(ts, addSecs); \n
if (v&gt;maxValue) \n if (v&gt;maxValue) \n
break; \n break; \n
} \n } \n
@@ -244,7 +276,9 @@
double maxValue; \n double maxValue; \n
GWEN_BUFFER *dbuf; \n GWEN_BUFFER *dbuf; \n
GWEN_DATE *dt; \n GWEN_DATE *dt; \n
int addSecs; \n
\n \n
addSecs=24*60*60; \n
maxValue=st-&gt;maxValue; \n maxValue=st-&gt;maxValue; \n
minValue=st-&gt;minValue; \n minValue=st-&gt;minValue; \n
dt=GWEN_Date_fromLocalTime(minValue); \n dt=GWEN_Date_fromLocalTime(minValue); \n
@@ -261,7 +295,7 @@
GWEN_Date_GetMonth(dt), \n GWEN_Date_GetMonth(dt), \n
GWEN_Date_GetDay(dt)); \n GWEN_Date_GetDay(dt)); \n
if (!$(struct_prefix)_HasTickValue(st, v)) \n if (!$(struct_prefix)_HasTickValue(st, v)) \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), v, lvl, 0); \n $(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), v, lvl, 0, (double) addSecs); \n
GWEN_Buffer_Reset(dbuf); \n GWEN_Buffer_Reset(dbuf); \n
} \n } \n
GWEN_Date_AddDays(dt, 1); \n GWEN_Date_AddDays(dt, 1); \n
@@ -290,6 +324,9 @@
double maxValue; \n double maxValue; \n
GWEN_BUFFER *dbuf; \n GWEN_BUFFER *dbuf; \n
GWEN_DATE *dt; \n GWEN_DATE *dt; \n
int addSecs; \n
\n
addSecs=7*24*60*60; \n
\n \n
maxValue=st-&gt;maxValue; \n maxValue=st-&gt;maxValue; \n
minValue=st-&gt;minValue; \n minValue=st-&gt;minValue; \n
@@ -314,7 +351,7 @@
GWEN_Date_GetMonth(dt), \n GWEN_Date_GetMonth(dt), \n
GWEN_Date_GetDay(dt)); \n GWEN_Date_GetDay(dt)); \n
if (!$(struct_prefix)_HasTickValue(st, v)) \n if (!$(struct_prefix)_HasTickValue(st, v)) \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), v, lvl, 0); \n $(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), v, lvl, 0, (double) addSecs); \n
GWEN_Buffer_Reset(dbuf); \n GWEN_Buffer_Reset(dbuf); \n
} \n } \n
GWEN_Date_AddDays(dt, 7); \n GWEN_Date_AddDays(dt, 7); \n
@@ -342,6 +379,9 @@
double maxValue; \n double maxValue; \n
GWEN_BUFFER *dbuf; \n GWEN_BUFFER *dbuf; \n
GWEN_DATE *dt; \n GWEN_DATE *dt; \n
int addSecs; \n
\n
addSecs=30*24*60*60; \n
\n \n
maxValue=st-&gt;maxValue; \n maxValue=st-&gt;maxValue; \n
dt=GWEN_Date_fromLocalTime(maxValue); \n dt=GWEN_Date_fromLocalTime(maxValue); \n
@@ -370,7 +410,7 @@
GWEN_Date_GetYear(dtCurrent), \n GWEN_Date_GetYear(dtCurrent), \n
GWEN_Date_GetMonth(dtCurrent)); \n GWEN_Date_GetMonth(dtCurrent)); \n
if (!$(struct_prefix)_HasTickValue(st, v)) \n if (!$(struct_prefix)_HasTickValue(st, v)) \n
$(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), v, lvl, 0); \n $(struct_prefix)_AddNewTick(st, GWEN_Buffer_GetStart(dbuf), v, lvl, 0, (double) addSecs); \n
GWEN_Buffer_Reset(dbuf); \n GWEN_Buffer_Reset(dbuf); \n
} \n } \n
GWEN_Date_free(dt); \n GWEN_Date_free(dt); \n

View File

@@ -56,6 +56,30 @@
</content> </content>
</inline> </inline>
<inline loc="end" access="public">
<content>
$(api) $(struct_type) *$(struct_prefix)_List_GetFirstTickForLevel(const $(struct_type)_LIST *tickList, int lvl);
</content>
</inline>
<inline loc="code">
<content>
$(struct_type) *$(struct_prefix)_List_GetFirstTickForLevel(const $(struct_type)_LIST *tickList, int lvl) \n
{ \n
$(struct_type) *tick; \n
\n
tick=$(struct_prefix)_List_First(tickList); \n
while(tick) { \n
if ($(struct_prefix)_GetLevel(tick)==lvl) \n
return tick; \n
tick=$(struct_prefix)_List_Next(tick); \n
} \n
return NULL; \n
} \n
</content>
</inline>
</inlines> </inlines>
@@ -85,6 +109,12 @@
<access>public</access> <access>public</access>
</member> </member>
<member name="levelDist" type="double" maxlen="8" >
<default>0.0</default>
<preset>0.0</preset>
<access>public</access>
</member>
<member name="flags" type="uint32_t" maxlen="8"> <member name="flags" type="uint32_t" maxlen="8">
<default>0</default> <default>0</default>
<preset>0</preset> <preset>0</preset>

View File

@@ -334,12 +334,19 @@ int _screenDistBetweenLevelTicksX(const AQDG_GRAPH_TICK_LIST *tickList, int lvl,
int _screenDistBetweenLevelTicksY(const AQDG_GRAPH_TICK_LIST *tickList, int lvl, int _screenDistBetweenLevelTicksY(const AQDG_GRAPH_TICK_LIST *tickList, int lvl,
int contentSize, double minValue, double maxValue) int contentSize, double minValue, double maxValue)
{ {
double v; const AQDG_GRAPH_TICK *firstLevelTick;
int pts;
v=AQDG_Graph_Tick_List_DistanceBetweenTicks(tickList, lvl); firstLevelTick=AQDG_Graph_Tick_List_GetFirstTickForLevel(tickList, lvl);
pts=(v*(contentSize/(maxValue-minValue))); if (firstLevelTick) {
return pts; double v;
int pts;
v=AQDG_Graph_Tick_GetLevelDist(firstLevelTick);
pts=(v*(contentSize/(maxValue-minValue)));
DBG_ERROR(NULL, "Level dist %d: %d", lvl, pts);
return pts;
}
return 0;
} }

View File

@@ -194,12 +194,19 @@ void _drawTicks(AQDG_OBJECT *o, AQDG_DRAW_CONTEXT *dc, int absX)
int _screenDistBetweenLevelTicks(const AQDG_GRAPH_TICK_LIST *tickList, int lvl, int _screenDistBetweenLevelTicks(const AQDG_GRAPH_TICK_LIST *tickList, int lvl,
int contentSize, double minValue, double maxValue) int contentSize, double minValue, double maxValue)
{ {
double v; const AQDG_GRAPH_TICK *firstLevelTick;
int pts;
v=AQDG_Graph_Tick_List_DistanceBetweenTicks(tickList, lvl); firstLevelTick=AQDG_Graph_Tick_List_GetFirstTickForLevel(tickList, lvl);
pts=(v*(contentSize/(maxValue-minValue))); if (firstLevelTick) {
return pts; double v;
int pts;
v=AQDG_Graph_Tick_GetLevelDist(firstLevelTick);
pts=(v*(contentSize/(maxValue-minValue)));
DBG_ERROR(NULL, "Level dist %d: %d", lvl, pts);
return pts;
}
return 0;
} }