Helper returns the mean direction vector from the given stats. Use the mean direction from dirs if there is information available, otherwise, use the fit_vector from point_diffs.
| 185 | // mean direction from dirs if there is information available, otherwise, use |
| 186 | // the fit_vector from point_diffs. |
| 187 | static FCOORD MeanDirectionVector(const LLSQ& point_diffs, const LLSQ& dirs, |
| 188 | const FCOORD& start_pt, |
| 189 | const FCOORD& end_pt) { |
| 190 | FCOORD fit_vector; |
| 191 | if (dirs.count() > 0) { |
| 192 | // There were directions, so use them. To avoid wrap-around problems, we |
| 193 | // have 2 accumulators in dirs: x for normal directions and y for |
| 194 | // directions offset by 128. We will use the one with the least variance. |
| 195 | FCOORD mean_pt = dirs.mean_point(); |
| 196 | double mean_dir = 0.0; |
| 197 | if (dirs.x_variance() <= dirs.y_variance()) { |
| 198 | mean_dir = mean_pt.x(); |
| 199 | } else { |
| 200 | mean_dir = mean_pt.y() + 128; |
| 201 | } |
| 202 | fit_vector.from_direction(Modulo(IntCastRounded(mean_dir), 256)); |
| 203 | } else { |
| 204 | // There were no directions, so we rely on the vector_fit to the points. |
| 205 | // Since the vector_fit is 180 degrees ambiguous, we align with the |
| 206 | // supplied feature_dir by making the scalar product non-negative. |
| 207 | FCOORD feature_dir(end_pt - start_pt); |
| 208 | fit_vector = point_diffs.vector_fit(); |
| 209 | if (fit_vector.x() == 0.0f && fit_vector.y() == 0.0f) { |
| 210 | // There was only a single point. Use feature_dir directly. |
| 211 | fit_vector = feature_dir; |
| 212 | } else { |
| 213 | // Sometimes the least mean squares fit is wrong, due to the small sample |
| 214 | // of points and scaling. Use a 90 degree rotated vector if that matches |
| 215 | // feature_dir better. |
| 216 | FCOORD fit_vector2 = !fit_vector; |
| 217 | // The fit_vector is 180 degrees ambiguous, so resolve the ambiguity by |
| 218 | // insisting that the scalar product with the feature_dir should be +ve. |
| 219 | if (fit_vector % feature_dir < 0.0) |
| 220 | fit_vector = -fit_vector; |
| 221 | if (fit_vector2 % feature_dir < 0.0) |
| 222 | fit_vector2 = -fit_vector2; |
| 223 | // Even though fit_vector2 has a higher mean squared error, it might be |
| 224 | // a better fit, so use it if the dot product with feature_dir is bigger. |
| 225 | if (fit_vector2 % feature_dir > fit_vector % feature_dir) |
| 226 | fit_vector = fit_vector2; |
| 227 | } |
| 228 | } |
| 229 | return fit_vector; |
| 230 | } |
| 231 | |
| 232 | // Helper computes one or more features corresponding to the given points. |
| 233 | // Emitted features are on the line defined by: |
no test coverage detected