51 pts_.emplace_back(pt, 0);
58 pts_.emplace_back(pt, halfwidth);
73 int pt_count = pts_.size();
75 if (skip_first >= pt_count) {
76 skip_first = pt_count - 1;
80 for (
int i = skip_first;
i < end_i; ++
i) {
81 starts[start_count++] = &pts_[
i].pt;
84 if (skip_last >= pt_count) {
85 skip_last = pt_count - 1;
89 for (
int i = pt_count - 1 - skip_last;
i >= end_i; --
i) {
90 ends[end_count++] = &pts_[
i].pt;
105 double best_uq = -1.0;
107 for (
int i = 0;
i < start_count; ++
i) {
109 for (
int j = 0; j < end_count; ++j) {
111 if (*start != *end) {
112 ComputeDistances(*start, *end);
114 double dist = EvaluateLineFit();
115 if (dist < best_uq || best_uq < 0.0) {
124 return best_uq > 0.0 ? sqrt(best_uq) : best_uq;
134 bool debug,
ICOORD *line_pt) {
135 ComputeConstrainedDistances(direction, min_dist, max_dist);
137 if (pts_.empty() || distances_.empty()) {
142 auto median_index = distances_.size() / 2;
143 std::nth_element(distances_.begin(), distances_.begin() + median_index, distances_.end());
144 *line_pt = distances_[median_index].data();
146 tprintf(
"Constrained fit to dir %g, %g = %d, %d :%zu distances:\n", direction.
x(), direction.
y(),
147 line_pt->
x(), line_pt->
y(), distances_.size());
148 for (
unsigned i = 0;
i < distances_.size(); ++
i) {
149 tprintf(
"%d: %d, %d -> %g\n",
i, distances_[
i].data().
x(), distances_[
i].data().
y(),
150 distances_[
i].key());
152 tprintf(
"Result = %zu\n", median_index);
155 double dist_origin = direction * *line_pt;
159 return sqrt(EvaluateLineFit());
173 double error =
Fit(&start, &end);
174 if (end.
x() != start.
x()) {
175 *m =
static_cast<float>(end.
y() - start.
y()) / (end.
x() - start.
x());
176 *c = start.
y() - *m * start.
x();
193 double cos = 1.0 / sqrt(1.0 + m * m);
194 FCOORD direction(cos, m * cos);
196 double error =
ConstrainedFit(direction, -FLT_MAX, FLT_MAX,
false, &line_pt);
197 *c = line_pt.
y() - line_pt.
x() * m;
202double DetLineFit::EvaluateLineFit() {
204 double dist = ComputeUpperQuartileError();
210 dist = NumberOfMisfittedPoints(threshold);
217double DetLineFit::ComputeUpperQuartileError() {
218 int num_errors = distances_.size();
219 if (num_errors == 0) {
223 for (
int i = 0;
i < num_errors; ++
i) {
224 if (distances_[
i].key() < 0) {
225 distances_[
i].key() = -distances_[
i].key();
229 auto index = 3 * num_errors / 4;
230 std::nth_element(distances_.begin(), distances_.begin() + index, distances_.end());
231 double dist = distances_[index].key();
234 return square_length_ > 0.0 ? dist * dist / square_length_ : 0.0;
238int DetLineFit::NumberOfMisfittedPoints(
double threshold)
const {
240 int num_dists = distances_.size();
242 for (
int i = 0;
i < num_dists; ++
i) {
243 if (distances_[
i].key() > threshold) {
254void DetLineFit::ComputeDistances(
const ICOORD &start,
const ICOORD &end) {
256 ICOORD line_vector = end;
257 line_vector -= start;
258 square_length_ = line_vector.sqlength();
261 int prev_abs_dist = 0;
263 for (
unsigned i = 0;
i < pts_.size(); ++
i) {
264 ICOORD pt_vector = pts_[
i].pt;
266 int dot = line_vector % pt_vector;
268 int dist = line_vector * pt_vector;
269 int abs_dist = dist < 0 ? -dist : dist;
270 if (abs_dist > prev_abs_dist &&
i > 0) {
272 int separation = abs(dot - prev_dot);
273 if (separation < line_length * pts_[
i].halfwidth ||
274 separation < line_length * pts_[
i - 1].halfwidth) {
278 distances_.emplace_back(dist, pts_[
i].pt);
279 prev_abs_dist = abs_dist;
287void DetLineFit::ComputeConstrainedDistances(
const FCOORD &direction,
double min_dist,
290 square_length_ = direction.sqlength();
292 for (
auto &pt : pts_) {
293 FCOORD pt_vector = pt.pt;
295 double dist = direction * pt_vector;
296 if (min_dist <= dist && dist <= max_dist) {
297 distances_.emplace_back(dist, pt.pt);
UnicodeText::const_iterator::difference_type distance(const UnicodeText::const_iterator &first, const UnicodeText::const_iterator &last)
const int kMaxRealDistance
void tprintf(const char *format,...)
int IntCastRounded(double x)
const int kMinPointsForErrorCount
void Add(const ICOORD &pt)
double ConstrainedFit(const FCOORD &direction, double min_dist, double max_dist, bool debug, ICOORD *line_pt)
double Fit(ICOORD *pt1, ICOORD *pt2)
bool SufficientPointsForIndependentFit() const
void set_x(TDimension xin)
rewrite function
TDimension y() const
access_function
void set_y(TDimension yin)
rewrite function
TDimension x() const
access function