Skip to content

Commit 0dcb7c6

Browse files
author
Mateusz Nabywaniec
committed
Fix annotation moving to the left when X axis PV changes
When on plot the X axis PV changes the way that there is no anymore the same x value, the annotation was choosing the last index before. When X axis PV is changing every time, it was causing the issue that annotation was slowly going to the left and finally ending at the beginning. Finding the closest sample instead should fix the issue.
1 parent 5cf6e87 commit 0dcb7c6

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

app/rtplot/src/main/java/org/csstudio/javafx/rtplot/data/PlotDataSearch.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
******************************************************************************/
88
package org.csstudio.javafx.rtplot.data;
99

10+
import java.util.Date;
11+
import java.time.Instant;
12+
1013
/** Search for samples in a haystack.
1114
* @author Kay Kasemir
1215
*/
@@ -125,4 +128,67 @@ final public int findSampleGreaterThan(final PlotDataProvider<XTYPE> data, final
125128
}
126129
return -1;
127130
}
131+
132+
/** Find the sample closest to the given value.
133+
* @param data Data, must already be locked
134+
* @param x The value to look for.
135+
* @return Index of sample closest to x, or -1 if data is empty or type unsupported.
136+
*/
137+
public int findClosestSample(final PlotDataProvider<XTYPE> data, final XTYPE x) {
138+
int low = 0;
139+
int high = data.size() - 1;
140+
141+
if (high < 0) return -1;
142+
143+
int bestIndex = -1;
144+
double bestDistance = Double.MAX_VALUE;
145+
146+
double target;
147+
try {
148+
target = toDouble(x);
149+
} catch (IllegalArgumentException e) {
150+
return -1;
151+
}
152+
153+
double distance;
154+
155+
while (low <= high) {
156+
int mid = (low + high) / 2;
157+
PlotDataItem<XTYPE> sample = data.get(mid);
158+
XTYPE sampleX = sample.getPosition();
159+
int cmp = sampleX.compareTo(x);
160+
161+
try{
162+
distance = Math.abs(toDouble(sampleX) - target);
163+
} catch (IllegalArgumentException e) {
164+
return -1;
165+
}
166+
167+
if (distance < bestDistance) {
168+
bestDistance = distance;
169+
bestIndex = mid;
170+
}
171+
172+
if (cmp == 0) {
173+
return mid;
174+
} else if (cmp < 0) {
175+
low = mid + 1;
176+
} else {
177+
high = mid - 1;
178+
}
179+
}
180+
181+
return bestIndex;
182+
}
183+
184+
/** Convert supported XTYPE to double for distance comparison */
185+
private double toDouble(XTYPE x) {
186+
if (x instanceof Number)
187+
return ((Number) x).doubleValue();
188+
if (x instanceof Instant)
189+
return ((Instant) x).toEpochMilli();
190+
if (x instanceof Date)
191+
return ((Date) x).getTime();
192+
throw new IllegalArgumentException("Unsupported XTYPE: " + x.getClass());
193+
}
128194
}

app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/AnnotationImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ boolean updateValue(final XTYPE location) throws Exception
179179
throw new TimeoutException("Cannot update annotation, no lock on " + data);
180180
try
181181
{
182-
final int index = search.findSampleLessOrEqual(data, location);
182+
final int index = search.findClosestSample(data, location);
183183
if (index < 0)
184184
return false;
185185
final PlotDataItem<XTYPE> sample = data.get(index);

0 commit comments

Comments
 (0)