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

View File

@@ -56,6 +56,30 @@
</content>
</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>
@@ -85,6 +109,12 @@
<access>public</access>
</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">
<default>0</default>
<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 contentSize, double minValue, double maxValue)
{
double v;
int pts;
const AQDG_GRAPH_TICK *firstLevelTick;
v=AQDG_Graph_Tick_List_DistanceBetweenTicks(tickList, lvl);
pts=(v*(contentSize/(maxValue-minValue)));
return pts;
firstLevelTick=AQDG_Graph_Tick_List_GetFirstTickForLevel(tickList, lvl);
if (firstLevelTick) {
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 contentSize, double minValue, double maxValue)
{
double v;
int pts;
const AQDG_GRAPH_TICK *firstLevelTick;
v=AQDG_Graph_Tick_List_DistanceBetweenTicks(tickList, lvl);
pts=(v*(contentSize/(maxValue-minValue)));
return pts;
firstLevelTick=AQDG_Graph_Tick_List_GetFirstTickForLevel(tickList, lvl);
if (firstLevelTick) {
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;
}