feat: Add include area button to narrow time range by selection
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
@@ -510,6 +510,63 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
|
|||||||
setSubmenu(false);
|
setSubmenu(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const includeArea = () => {
|
||||||
|
const drawnRectangles = drawnItems.map(item => item.bounds);
|
||||||
|
if (!drawnRectangles.length || !data || !Array.isArray(data)) {
|
||||||
|
if (!drawnRectangles.length) alert("Please draw one or more rectangles on the map first.");
|
||||||
|
setSubmenu(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isInsideInclusionZone = (lat, lon) => {
|
||||||
|
for (const rect of drawnRectangles) {
|
||||||
|
if (rect.contains([lat, lon])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let minTime = null;
|
||||||
|
let maxTime = null;
|
||||||
|
|
||||||
|
for (const point of data) {
|
||||||
|
if (!point || typeof point.lat !== 'number' || typeof point.lon !== 'number' || !point.time) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isInside = isInsideInclusionZone(point.lat, point.lon);
|
||||||
|
|
||||||
|
if (isInside) {
|
||||||
|
if (minTime === null || point.time < minTime) {
|
||||||
|
minTime = point.time;
|
||||||
|
}
|
||||||
|
if (maxTime === null || point.time > maxTime) {
|
||||||
|
maxTime = point.time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minTime === null) {
|
||||||
|
alert("No data points found inside the selected area(s).");
|
||||||
|
setSubmenu(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const startUnix = moment(minTime).unix();
|
||||||
|
const endUnix = moment(maxTime).unix();
|
||||||
|
const endOfWindowUnix = end.unix();
|
||||||
|
|
||||||
|
const newSliderStart = Math.floor((startUnix - endOfWindowUnix) / duration.secs + duration.num);
|
||||||
|
const newSliderEnd = Math.ceil((endUnix - endOfWindowUnix) / duration.secs + duration.num);
|
||||||
|
|
||||||
|
const clampedStart = Math.max(0, newSliderStart);
|
||||||
|
const clampedEnd = Math.min(duration.num, newSliderEnd);
|
||||||
|
|
||||||
|
setSlider([clampedStart, clampedEnd]);
|
||||||
|
setSubmenu(false);
|
||||||
|
};
|
||||||
|
|
||||||
const searchArea = async () => {
|
const searchArea = async () => {
|
||||||
const drawnRectangles = drawnItems.map(item => item.bounds);
|
const drawnRectangles = drawnItems.map(item => item.bounds);
|
||||||
if (!drawnRectangles.length) {
|
if (!drawnRectangles.length) {
|
||||||
@@ -837,6 +894,7 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
|
|||||||
</label>
|
</label>
|
||||||
<button onClick={recentreView}>Recentre view</button>
|
<button onClick={recentreView}>Recentre view</button>
|
||||||
<button onClick={excludeArea}>Exclude area</button>
|
<button onClick={excludeArea}>Exclude area</button>
|
||||||
|
<button onClick={includeArea}>Include area</button>
|
||||||
<button onClick={searchArea} disabled={isSearching}>
|
<button onClick={searchArea} disabled={isSearching}>
|
||||||
{isSearching ? 'Searching...' : 'Search area'}
|
{isSearching ? 'Searching...' : 'Search area'}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user