]> rtime.felk.cvut.cz Git - hubacji1/bcar.git/blob - src/bcar.cc
Add operator<< for line
[hubacji1/bcar.git] / src / bcar.cc
1 #include <cmath>
2 #include "bcar.hh"
3
4 namespace bcar {
5
6 Point::Point(double x, double y) : x_(x), y_(y)
7 {
8 }
9
10 Point::Point() : Point::Point(0.0, 0.0)
11 {
12 }
13
14 double
15 Point::x() const
16 {
17         return this->x_;
18 }
19
20 void
21 Point::x(double x)
22 {
23         this->x_ = x;
24 }
25
26 double
27 Point::y() const
28 {
29         return this->y_;
30 }
31
32 void
33 Point::y(double y)
34 {
35         this->y_ = y;
36 }
37
38 double
39 Point::min_angle_between(Point const& p1, Point const& p2) const
40 {
41         double d1x = p1.x() - this->x();
42         double d1y = p1.y() - this->y();
43         double d2x = p2.x() - p1.x();
44         double d2y = p2.y() - p1.y();
45
46         double dot = d1x*d2x + d1y*d2y;
47         double d1 = sqrt(d1x*d1x + d1y*d1y);
48         double d2 = sqrt(d2x*d2x + d2y*d2y);
49
50         double delta = acos(dot / (d1 * d2));
51         return std::min(delta, M_PI - delta);
52 }
53
54 bool
55 Point::inside_of(std::vector<Point> const& poly) const
56 {
57         unsigned int num = poly.size();
58         unsigned int j = num - 1;
59         bool c = false;
60         for (unsigned int i = 0; i < num; i++) {
61                 if (this->x() == poly[i].x() && this->y() == poly[i].y()) {
62                         return true;
63                 }
64                 if ((poly[i].y() > this->y()) != (poly[j].y() > this->y())) {
65                         auto slope1 = this->x() - poly[i].x();
66                         slope1 *= poly[j].y() - poly[i].y();
67                         auto slope2 = poly[j].x() - poly[i].x();
68                         slope2 *= this->y() - poly[i].y();
69                         auto slope = slope1 - slope2;
70                         if (slope == 0.0) {
71                                 return true;
72                         }
73                         if ((slope < 0.0) != (poly[j].y() < poly[i].y())) {
74                                 c = !c;
75                         }
76                 }
77                 j = i;
78         }
79         return c;
80 }
81
82 bool
83 Point::on_right_side_of(Line const& li) const
84 {
85         auto x1 = li.fp().x();
86         auto y1 = li.fp().y();
87         auto x2 = li.lp().x();
88         auto y2 = li.lp().y();
89         auto x3 = this->x_;
90         auto y3 = this->y_;
91         if (sgn((x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1)) < 0.0) {
92                 return false;
93         } else {
94                 return true;
95         }
96 }
97
98 void
99 Point::rotate(Point const& c, double const angl)
100 {
101         double px = this->x();
102         double py = this->y();
103         px -= c.x();
104         py -= c.y();
105         double nx = px * cos(angl) - py * sin(angl);
106         double ny = px * sin(angl) + py * cos(angl);
107         this->x(nx + c.x());
108         this->y(ny + c.y());
109 }
110
111 std::ostream&
112 operator<<(std::ostream& out, Point const& p)
113 {
114         out << "[" << p.x() << "," << p.y() << "]";
115         return out;
116 }
117
118 Line::Line(Point const& fp, Point const& lp): first(fp), last(lp),
119                 intersection1(Point(0.0, 0.0)), intersection2(Point(0.0, 0.0))
120 {
121 }
122
123 Point
124 Line::fp() const&
125 {
126         return this->first;
127 }
128
129 Point
130 Line::lp() const&
131 {
132         return this->last;
133 }
134
135 Point
136 Line::in1() const&
137 {
138         return this->intersection1;
139 }
140
141 Point
142 Line::in2() const&
143 {
144         return this->intersection2;
145 }
146
147 bool
148 Line::intersects_with(Line const& li)
149 {
150         auto x1 = this->fp().x();
151         auto y1 = this->fp().y();
152         auto x2 = this->lp().x();
153         auto y2 = this->lp().y();
154         auto x3 = li.fp().x();
155         auto y3 = li.fp().y();
156         auto x4 = li.lp().x();
157         auto y4 = li.lp().y();
158         double deno = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
159         if (deno == 0.0) {
160                 return false;
161         }
162         double t = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4);
163         t /= deno;
164         double u = (x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3);
165         u *= -1.0;
166         u /= deno;
167         if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0) {
168                 return false;
169         }
170         this->intersection1.x(x1 + t * (x2 - x1));
171         this->intersection1.y(y1 + t * (y2 - y1));
172         return true;
173 }
174
175 bool
176 Line::intersects_with(Point const& c, double const r)
177 {
178         auto x1 = this->fp().x();
179         auto y1 = this->fp().y();
180         auto x2 = this->lp().x();
181         auto y2 = this->lp().y();
182         auto cx = c.x();
183         auto cy = c.y();
184         x2 -= cx;
185         x1 -= cx;
186         y2 -= cy;
187         y1 -= cy;
188         if (y1 == y2) {
189                 y1 += 0.00001;
190         }
191         double dx = x2 - x1;
192         double dy = y2 - y1;
193         double dr = sqrt(dx*dx + dy*dy);
194         double D = x1*y2 - x2*y1;
195         if (r*r * dr*dr - D*D < 0.0) {
196                 return false;
197         }
198         // intersection coordinates
199         double ix1 = (D*dy + sgn(dy)*dx*sqrt(r*r * dr*dr - D*D)) / (dr*dr);
200         ix1 += cx;
201         double ix2 = (D*dy - sgn(dy)*dx*sqrt(r*r * dr*dr - D*D)) / (dr*dr);
202         ix2 += cx;
203         double iy1 = (-D*dx + std::abs(dy)*sqrt(r*r * dr*dr - D*D)) / (dr*dr);
204         iy1 += cy;
205         double iy2 = (-D*dx - std::abs(dy)*sqrt(r*r * dr*dr - D*D)) / (dr*dr);
206         iy2 += cy;
207         this->intersection1.x(ix1);
208         this->intersection1.y(iy1);
209         this->intersection2.x(ix2);
210         this->intersection2.y(iy2);
211         return true;
212 }
213
214 double
215 Line::len() const
216 {
217         double dx = this->lp().x() - this->fp().x();
218         double dy = this->lp().y() - this->fp().y();
219         return sqrt(dx * dx + dy * dy);
220 }
221
222 std::ostream&
223 operator<<(std::ostream& out, Line const& li)
224 {
225         out << "[" << li.first << "," << li.last << "]";
226         return out;
227 }
228
229 Pose::Pose() : Point()
230 {
231 }
232
233 Pose::Pose(double x, double y, double h) : Point(x, y), h_(h)
234 {
235 }
236
237 double
238 Pose::h() const
239 {
240         return this->h_;
241 }
242
243 void
244 Pose::h(double h)
245 {
246         while (h < -M_PI) {
247                 h += 2 * M_PI;
248         }
249         while (h > +M_PI) {
250                 h -= 2 * M_PI;
251         }
252         this->h_ = h;
253 }
254
255 void
256 Pose::set_pose(Pose const& p)
257 {
258         this->x(p.x());
259         this->y(p.y());
260         this->h(p.h());
261 }
262
263 void
264 Pose::rotate(Point const& c, double const angl)
265 {
266         Point::rotate(c, angl);
267         this->h(this->h() + angl);
268 }
269
270 std::ostream&
271 operator<<(std::ostream& out, Pose const& p)
272 {
273         out << "[" << p.x() << "," << p.y() << "," << p.h() << "]";
274         return out;
275 }
276
277 double
278 PoseRange::b() const
279 {
280         return this->h();
281 }
282
283 void
284 PoseRange::b(double b)
285 {
286         this->h(b);
287 }
288
289 double
290 PoseRange::e() const
291 {
292         return this->e_;
293 }
294
295 void
296 PoseRange::e(double e)
297 {
298         while (e < -M_PI) {
299                 e += 2 * M_PI;
300         }
301         while (e > +M_PI) {
302                 e -= 2 * M_PI;
303         }
304         this->e_ = e;
305 }
306
307 void
308 PoseRange::rotate(Point const& c, double const angl)
309 {
310         Pose::rotate(c, angl);
311         this->e(this->e() + angl);
312 }
313
314 std::ostream&
315 operator<<(std::ostream& out, PoseRange const& p)
316 {
317         out << "[" << p.x() << "," << p.y() << "," << p.b() << "," << p.e();
318         out << "]";
319         return out;
320 }
321
322 double
323 CarSize::ctc() const
324 {
325         return this->curb_to_curb;
326 }
327
328 void
329 CarSize::ctc(double ctc)
330 {
331         this->curb_to_curb = ctc;
332 }
333
334 double
335 CarSize::wb() const
336 {
337         return this->wheelbase;
338 }
339
340 void
341 CarSize::wb(double wb)
342 {
343         this->wheelbase = wb;
344 }
345
346 double
347 CarSize::w() const
348 {
349         return this->width;
350 }
351
352 void
353 CarSize::w(double w)
354 {
355         this->width = w;
356 }
357
358 double
359 CarSize::len() const
360 {
361         return this->length;
362 }
363
364 void
365 CarSize::len(double len)
366 {
367         this->length = len;
368 }
369
370 double
371 CarSize::df() const
372 {
373         return this->distance_to_front;
374 }
375
376 void
377 CarSize::df(double df)
378 {
379         this->distance_to_front = df;
380 }
381
382 double
383 CarSize::dr() const
384 {
385         return this->len() - this->df();
386 }
387
388 double
389 CarSize::mtr() const
390 {
391         auto ctc2 = pow(this->ctc() / 2.0, 2.0);
392         auto wb2 = pow(this->wb(), 2.0);
393         return sqrt(ctc2 - wb2) - this->w() / 2.0;
394 }
395
396 double
397 CarSize::iradi() const
398 {
399         return this->mtr() - this->w() / 2;
400 }
401
402 double
403 CarSize::ofradi() const
404 {
405         auto mtrw2 = pow(this->mtr() + this->w() / 2.0, 2.0);
406         auto df2 = pow(this->df(), 2.0);
407         return sqrt(mtrw2 + df2);
408 }
409
410 double
411 CarSize::orradi() const
412 {
413         auto mtrw2 = pow(this->mtr() + this->w() / 2.0, 2.0);
414         auto dr2 = pow(this->dr(), 2.0);
415         return sqrt(mtrw2 + dr2);
416 }
417
418 double
419 CarSize::perfect_parking_slot_len() const
420 {
421         auto r = this->ctc() / 2.0;
422         auto l = this->wb();
423         auto k = this->df() - this->wb();
424         auto w = this->w();
425         auto r2l2 = r * r - l * l;
426         auto s = r2l2 + pow(l + k, 2.0) - pow(sqrt(r2l2) - w, 2.0);
427         return this->len() + sqrt(s) - l - k;
428 }
429
430 double
431 CarMove::sp() const
432 {
433         return this->speed;
434 }
435
436 void
437 CarMove::sp(double sp)
438 {
439         this->speed = sp;
440 }
441
442 double
443 CarMove::st() const
444 {
445         return this->steer;
446 }
447
448 void
449 CarMove::st(double st)
450 {
451         this->steer = st;
452 }
453
454 bool
455 BicycleCar::drivable(Pose const& p) const
456 {
457         PoseRange pr;
458         pr.x(p.x());
459         pr.y(p.y());
460         pr.b(p.h());
461         pr.e(p.h());
462         return this->drivable(pr);
463 }
464
465 bool
466 BicycleCar::drivable(PoseRange const& p) const
467 {
468         double h = (p.b() + p.e()) / 2.0;
469         double a_1 = atan2(p.y() - this->y(), p.x() - this->x()) - this->h();
470         while (a_1 < -M_PI)
471                 a_1 += 2 * M_PI;
472         while (a_1 > +M_PI)
473                 a_1 -= 2 * M_PI;
474         double h_d = h - this->h();
475         while (h_d < -M_PI)
476                 h_d += 2 * M_PI;
477         while (h_d > +M_PI)
478                 h_d -= 2 * M_PI;
479         double a_2 = 0;
480         if (h_d == 0 && (a_1 == 0 || a_2 == M_PI || a_2 == -M_PI)) {
481                 return true;
482         } else if (0 < a_1 && a_1 <= M_PI/2) { // left front
483                 BicycleCar z(*this); // zone border
484                 z.h(p.e());
485                 h_d = h - this->h();
486                 z.rotate(this->ccl(), h_d);
487                 // assert z.h() == h
488                 if (p.y() == z.y() && p.x() == z.x()) // p on zone border
489                         return true;
490                 a_2 = atan2(p.y() - z.y(), p.x() - z.x());
491                 while (a_2 < -M_PI)
492                         a_2 += 2 * M_PI;
493                 while (a_2 > +M_PI)
494                         a_2 -= 2 * M_PI;
495                 if (z.h() >= a_2 && a_2 >= this->h())
496                         return true;
497         } else if (M_PI/2 < a_1 && a_1 <= M_PI) { // left rear
498                 BicycleCar z(*this); // zone border
499                 z.h(p.e());
500                 h_d = h - this->h();
501                 z.rotate(this->ccl(), h_d);
502                 // assert z.h() == h
503                 if (p.y() == z.y() && p.x() == z.x()) // p on zone border
504                         return true;
505                 a_2 = atan2(p.y() - z.y(), p.x() - z.x());
506                 a_2 -= M_PI;
507                 while (a_2 < -M_PI)
508                         a_2 += 2 * M_PI;
509                 while (a_2 > +M_PI)
510                         a_2 -= 2 * M_PI;
511                 if (this->h() >= a_2 && a_2 >= z.h())
512                         return true;
513         } else if (0 > a_1 && a_1 >= -M_PI/2) { // right front
514                 BicycleCar z(*this); // zone border
515                 z.h(p.b());
516                 h_d = h - this->h();
517                 z.rotate(this->ccr(), h_d);
518                 // assert z.h() == h
519                 if (p.y() == z.y() && p.x() == z.x()) // p on zone border
520                         return true;
521                 a_2 = atan2(p.y() - z.y(), p.x() - z.x());
522                 while (a_2 < -M_PI)
523                         a_2 += 2 * M_PI;
524                 while (a_2 > +M_PI)
525                         a_2 -= 2 * M_PI;
526                 if (this->h() >= a_2 && a_2 >= z.h())
527                         return true;
528         } else if (-M_PI/2 > a_1 && a_1 >= -M_PI) { // right rear
529                 BicycleCar z(*this); // zone border
530                 z.h(p.b());
531                 h_d = h - this->h();
532                 z.rotate(this->ccr(), h_d);
533                 // assert z.h() == h
534                 if (p.y() == z.y() && p.x() == z.x()) // p on zone border
535                         return true;
536                 a_2 = atan2(p.y() - z.y(), p.x() - z.x());
537                 a_2 -= M_PI;
538                 while (a_2 < -M_PI)
539                         a_2 += 2 * M_PI;
540                 while (a_2 > +M_PI)
541                         a_2 -= 2 * M_PI;
542                 if (z.h() >= a_2 && a_2 >= this->h())
543                         return true;
544         } else {
545                 // Not happenning, as ``-pi <= a <= pi``.
546         }
547         return false;
548 }
549
550 void
551 BicycleCar::set_max_steer()
552 {
553         this->st(atan(this->wb() / this->mtr()));
554 }
555
556 double
557 BicycleCar::lfx() const
558 {
559         double lfx = this->x();
560         lfx += (this->w() / 2.0) * cos(this->h() + M_PI / 2.0);
561         lfx += this->df() * cos(this->h());
562         return lfx;
563 }
564
565 double
566 BicycleCar::lfy() const
567 {
568         double lfy = this->y();
569         lfy += (this->w() / 2.0) * sin(this->h() + M_PI / 2.0);
570         lfy += this->df() * sin(this->h());
571         return lfy;
572 }
573
574 double
575 BicycleCar::lrx() const
576 {
577         double lrx = this->x();
578         lrx += (this->w() / 2.0) * cos(this->h() + M_PI / 2.0);
579         lrx += -this->dr() * cos(this->h());
580         return lrx;
581 }
582
583 double
584 BicycleCar::lry() const
585 {
586         double lry = this->y();
587         lry += (this->w() / 2.0) * sin(this->h() + M_PI / 2.0);
588         lry += -this->dr() * sin(this->h());
589         return lry;
590 }
591
592 double
593 BicycleCar::rrx() const
594 {
595         double rrx = this->x();
596         rrx += (this->w() / 2.0) * cos(this->h() - M_PI / 2.0);
597         rrx += -this->dr() * cos(this->h());
598         return rrx;
599 }
600
601 double
602 BicycleCar::rry() const
603 {
604         double rry = this->y();
605         rry += (this->w() / 2.0) * sin(this->h() - M_PI / 2.0);
606         rry += -this->dr() * sin(this->h());
607         return rry;
608 }
609
610 double
611 BicycleCar::rfx() const
612 {
613         double rfx = this->x();
614         rfx += (this->w() / 2.0) * cos(this->h() - M_PI / 2.0);
615         rfx += this->df() * cos(this->h());
616         return rfx;
617 }
618
619 double
620 BicycleCar::rfy() const
621 {
622         double rfy = this->y();
623         rfy += (this->w() / 2.0) * sin(this->h() - M_PI / 2.0);
624         rfy += this->df() * sin(this->h());
625         return rfy;
626 }
627
628 double
629 BicycleCar::ralx() const
630 {
631         double lrx = this->x();
632         lrx += (this->w() / 2.0) * cos(this->h() + M_PI / 2.0);
633         return lrx;
634 }
635 double
636 BicycleCar::raly() const
637 {
638         double lry = this->y();
639         lry += (this->w() / 2.0) * sin(this->h() + M_PI / 2.0);
640         return lry;
641 }
642
643 double
644 BicycleCar::rarx() const
645 {
646         double rrx = this->x();
647         rrx += (this->w() / 2.0) * cos(this->h() - M_PI / 2.0);
648         return rrx;
649 }
650
651 double
652 BicycleCar::rary() const
653 {
654         double rry = this->y();
655         rry += (this->w() / 2.0) * sin(this->h() - M_PI / 2.0);
656         return rry;
657 }
658
659 Point
660 BicycleCar::ccl() const
661 {
662         return Point(
663                 this->x() + this->mtr() * cos(this->h() + M_PI / 2.0),
664                 this->y() + this->mtr() * sin(this->h() + M_PI / 2.0)
665         );
666 }
667
668 Point
669 BicycleCar::ccr() const
670 {
671         return Point(
672                 this->x() + this->mtr() * cos(this->h() - M_PI / 2.0),
673                 this->y() + this->mtr() * sin(this->h() - M_PI / 2.0)
674         );
675 }
676
677 void
678 BicycleCar::next()
679 {
680         this->x(this->x() + this->sp() * cos(this->h()));
681         this->y(this->y() + this->sp() * sin(this->h()));
682         this->h(this->h() + this->sp() / this->wb() * tan(this->st()));
683 }
684
685 } // namespace bcar