• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

paulmthompson / WhiskerToolbox / 17344483100

30 Aug 2025 01:39PM UTC coverage: 67.624% (+0.5%) from 67.086%
17344483100

push

github

paulmthompson
added line resample testing

290 of 306 new or added lines in 2 files covered. (94.77%)

27817 of 41135 relevant lines covered (67.62%)

1101.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.64
/src/DataManager/transforms/Lines/Line_Resample/line_resample.cpp
1
#include "line_resample.hpp"
2

3
#include "CoreGeometry/line_resampling.hpp"// For the actual resampling
4
#include "Lines/Line_Data.hpp"
5

6
#include <iostream>// For error messages / cout
7
#include <map>     // for std::map
8

9
std::shared_ptr<LineData> line_resample(
5✔
10
        LineData const * line_data,
11
        LineResampleParameters const & params) {
12
    // Call the version with a null progress callback
13
    return line_resample(line_data, params, nullptr);
5✔
14
}
15

16
/**
17
 * @brief Resamples lines in a LineData object based on the specified algorithm, with progress reporting.
18
 *
19
 * This function processes all lines in the input LineData object using the specified algorithm
20
 * (FixedSpacing or Douglas-Peucker) and returns a new LineData object with the resampled lines.
21
 *
22
 * @param line_data A pointer to the input LineData object. Must not be null.
23
 * @param params A struct containing the algorithm type, target spacing (for FixedSpacing),
24
 *               and epsilon value (for Douglas-Peucker).
25
 * @param progressCallback An optional function that can be called to report progress (0-100).
26
 *                         If nullptr, progress is not reported.
27
 * @return A std::shared_ptr<LineData> containing the resampled lines.
28
 *         Returns an empty LineData if line_data is null or has no data.
29
 */
30
std::shared_ptr<LineData> line_resample(
9✔
31
        LineData const * line_data,
32
        LineResampleParameters const & params,
33
        ProgressCallback progressCallback) {
34
    auto result_line_data = std::make_shared<LineData>();
9✔
35

36
    if (!line_data) {
9✔
NEW
37
        std::cerr << "Error: line_data is null." << std::endl;
×
NEW
38
        return result_line_data;
×
39
    }
40

41
    std::cout << "LineResampleOperation: algorithm = "
42
              << (params.algorithm == LineSimplificationAlgorithm::FixedSpacing ? "FixedSpacing" : "DouglasPeucker")
9✔
43
              << ", target_spacing = " << params.target_spacing
9✔
44
              << ", epsilon = " << params.epsilon << std::endl;
9✔
45

46
    auto resampled_line_map = std::map<TimeFrameIndex, std::vector<Line2D>>();
9✔
47
    int total_lines = 0;
9✔
48
    for (auto const & time_lines_pair: line_data->GetAllLinesAsRange()) {
23✔
49
        total_lines += static_cast<int>(time_lines_pair.lines.size());
14✔
50
    }
51
    if (total_lines == 0) {
9✔
52
        if (progressCallback) {
1✔
NEW
53
            progressCallback(100);// No data to process, so 100% complete.
×
54
        }
55
        result_line_data->setImageSize(line_data->getImageSize());
1✔
56
        return result_line_data;
1✔
57
    }
58

59
    int processed_lines = 0;
8✔
60
    if (progressCallback) {
8✔
61
        progressCallback(0);
4✔
62
    }
63

64
    for (auto const & time_lines_pair: line_data->GetAllLinesAsRange()) {
22✔
65
        TimeFrameIndex time = time_lines_pair.time;
14✔
66
        std::vector<Line2D> new_lines_at_time;
14✔
67
        new_lines_at_time.reserve(time_lines_pair.lines.size());
14✔
68

69
        for (auto const & single_line: time_lines_pair.lines) {
28✔
70
            if (single_line.empty()) {
14✔
71
                new_lines_at_time.push_back(Line2D());// Keep empty lines as empty
1✔
72
            } else {
73
                Line2D simplified_line;
13✔
74
                switch (params.algorithm) {
13✔
75
                    case LineSimplificationAlgorithm::FixedSpacing:
10✔
76
                        simplified_line = resample_line_points(single_line, params.target_spacing);
10✔
77
                        break;
10✔
78
                    case LineSimplificationAlgorithm::DouglasPeucker:
3✔
79
                        simplified_line = douglas_peucker_simplify(single_line, params.epsilon);
3✔
80
                        break;
3✔
81
                }
82
                new_lines_at_time.push_back(simplified_line);
13✔
83
            }
13✔
84
            processed_lines++;
14✔
85
            if (progressCallback && total_lines > 0) {
14✔
86
                int const current_progress = static_cast<int>((static_cast<double>(processed_lines) / total_lines) * 100.0);
8✔
87
                progressCallback(current_progress);
8✔
88
            }
89
        }
90
        if (!new_lines_at_time.empty() || line_data->getAtTime(time).empty()) {
14✔
91
            // Add to map if there are new lines OR if the original time had lines (even if all became empty)
92
            // This ensures that times that previously had data but now have all empty lines are still represented.
93
            // However, if a time originally had no lines, we don't add an empty entry for it.
94
            if (!line_data->getAtTime(time).empty() || !new_lines_at_time.empty()) {
14✔
95
                resampled_line_map[time] = std::move(new_lines_at_time);
14✔
96
            }
97
        }
98
    }
14✔
99

100
    result_line_data = std::make_shared<LineData>(resampled_line_map);
8✔
101
    result_line_data->setImageSize(line_data->getImageSize());// Preserve image size
8✔
102

103
    if (progressCallback) {
8✔
104
        progressCallback(100);// Ensure 100% is reported at the end.
4✔
105
    }
106
    std::cout << "LineResampleOperation executed successfully." << std::endl;
8✔
107
    return result_line_data;
8✔
108
}
9✔
109

110
///////////////////////////////////////////////////////////////////////////////
111

112
std::string LineResampleOperation::getName() const {
44✔
113
    return "Resample Line";
132✔
114
}
115

116
std::type_index LineResampleOperation::getTargetInputTypeIndex() const {
44✔
117
    return typeid(std::shared_ptr<LineData>);
44✔
118
}
119

120
bool LineResampleOperation::canApply(DataTypeVariant const & dataVariant) const {
3✔
121
    if (!std::holds_alternative<std::shared_ptr<LineData>>(dataVariant)) {
3✔
NEW
122
        return false;
×
123
    }
124
    auto const * ptr_ptr = std::get_if<std::shared_ptr<LineData>>(&dataVariant);
3✔
125
    return ptr_ptr && *ptr_ptr;// Check if it's a valid, non-null LineData
3✔
126
}
127

128
std::unique_ptr<TransformParametersBase> LineResampleOperation::getDefaultParameters() const {
3✔
129
    return std::make_unique<LineResampleParameters>();
3✔
130
}
131

132
DataTypeVariant LineResampleOperation::execute(DataTypeVariant const & dataVariant,
1✔
133
                                               TransformParametersBase const * transformParameters) {
134
    // Call the version with progress reporting but ignore progress here
135
    return execute(dataVariant, transformParameters, [](int) {});
1✔
136
}
137

138
DataTypeVariant LineResampleOperation::execute(DataTypeVariant const & dataVariant,
3✔
139
                                               TransformParametersBase const * transformParameters,
140
                                               ProgressCallback progressCallback) {
141
    auto const * line_data_sptr_ptr = std::get_if<std::shared_ptr<LineData>>(&dataVariant);
3✔
142
    if (!line_data_sptr_ptr || !(*line_data_sptr_ptr)) {
3✔
NEW
143
        std::cerr << "LineResampleOperation::execute called with incompatible variant type or null data." << std::endl;
×
NEW
144
        if (progressCallback) progressCallback(100);// Indicate completion even on error
×
NEW
145
        return {};// Return empty variant
×
146
    }
147
    LineData const * input_line_data = (*line_data_sptr_ptr).get();
3✔
148

149
    LineResampleParameters currentParams;// Default parameters
3✔
150

151
    if (transformParameters != nullptr) {
3✔
152
        auto const * specificParams = dynamic_cast<LineResampleParameters const *>(transformParameters);
3✔
153

154
        if (specificParams) {
3✔
155
            currentParams = *specificParams;
3✔
156
            // std::cout << "Using parameters provided by UI." << std::endl; // Debug, consider removing
157
        } else {
NEW
158
            std::cerr << "Warning: LineResampleOperation received incompatible parameter type (dynamic_cast failed)! Using default parameters." << std::endl;
×
159
            // Fall through to use the default 'currentParams'
160
        }
161
    } else {
162
        // std::cout << "LineResampleOperation received null parameters. Using default parameters." << std::endl; // Debug, consider removing
163
        // Fall through to use the default 'currentParams'
164
    }
165

166
    std::shared_ptr<LineData> result_line_data = line_resample(input_line_data,
3✔
167
                                                               currentParams,
168
                                                               progressCallback);
3✔
169

170
    if (!result_line_data) {
3✔
NEW
171
        std::cerr << "LineResampleOperation::execute: 'line_resample' failed to produce a result." << std::endl;
×
NEW
172
        if (progressCallback) progressCallback(100);// Indicate completion even on error
×
NEW
173
        return {};// Return empty
×
174
    }
175

176
    // std::cout << "LineResampleOperation executed successfully using variant input." << std::endl; // Debug, consider removing
177
    if (progressCallback) progressCallback(100);// Ensure 100% is reported at the end.
3✔
178
    return result_line_data;
3✔
179
}
3✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc