15 # include <autosprintf.h>
18 typedef mpq_class Geom_Number;
20 inline double geom_number_to_double(
const Geom_Number & n)
29 const double PI = 3.1415926535897932384626433832795028841971693993751;
30 const double PI_2 = PI/2;
31 const double PI_4 = PI_2/2.0;
42 area_of_parallelogram(
const Point & a,
const Point & b,
const Point & c);
46 inline Geom_Number pitag(
const Geom_Number & x,
const Geom_Number & y)
48 return hypot(mpfr_class(x), mpfr_class(y));
51 inline Geom_Number arctan(
const Geom_Number & m)
53 return atan(mpfr_class(m));
56 inline Geom_Number sinus(
const Geom_Number & x)
58 return sin(mpfr_class(x));
61 inline Geom_Number cosinus(
const Geom_Number & x)
63 return cos(mpfr_class(x));
66 inline Geom_Number square_root(
const Geom_Number & x)
68 return sqrt(mpfr_class(x));
101 Point(
const Geom_Number & __x,
const Geom_Number & __y)
119 return x == point.x and y == point.y;
125 return not (*
this == point);
132 return Point(x + p.x, y + p.y);
149 return Point(x - p.x, y - p.y);
174 return area_of_parallelogram(*
this, p1, p2) == 0;
184 return area_of_parallelogram(p1, p2, *
this) > 0;
191 return area_of_parallelogram(p1, p2, *
this) < 0;
197 return area_of_parallelogram(*
this, p1, p2) < 0;
223 return this->y >= p1.y and this->y <= p2.y;
227 return this->x >= p1.x and this->x <= p2.x;
248 return gnu::autosprintf(
"(%.1f,%.1f)", geom_number_to_double(x),
249 geom_number_to_double(y));
261 const Point & highest_point()
const {
return *
this; }
263 const Point & lowest_point()
const {
return *
this; }
265 const Point & leftmost_point()
const {
return *
this; }
267 const Point & rightmost_point()
const {
return *
this; }
270 extern const Point NullPoint;
293 const Geom_Number &
get_r()
const {
return r; }
298 Polar_Point(
const Geom_Number & __r,
const Geom_Number & __theta)
299 : r(__r), theta(__theta)
307 const Geom_Number & x = p.x;
308 const Geom_Number & y = p.y;
316 theta = y >= 0 ? PI/2 : 3*PI/2;
323 theta = x >= 0 ? 0 : PI;
343 if (r > 0 and theta > 0)
358 return gnu::autosprintf(
"[%.1f,%.1f]", geom_number_to_double(r),
359 geom_number_to_double(theta));
368 : x(pp.r * cosinus(pp.theta)), y(pp.r * sinus(pp.theta))
385 double compute_slope()
const
390 return std::numeric_limits<double>::max();
392 return - std::numeric_limits<double>::max();
395 const Geom_Number __slope = (tgt.y - src.y) / (tgt.x - src.x);
397 return __slope.get_d();
402 bool operator == (
const Segment & s)
const
404 return src == s.src and tgt == s.tgt;
407 bool operator != (
const Segment & s)
const
409 return not (*
this == s);
415 return src.y > tgt.y ? src : tgt;
421 return src.y < tgt.y ? src : tgt;
427 return src.x < tgt.x ? src : tgt;
433 return src.x > tgt.x ? src : tgt;
472 const Geom_Number & m,
473 const Geom_Number & d)
475 const Geom_Number den2 = 1 + m*m;
477 const Geom_Number den = square_root(den2);
479 const Geom_Number x = __src.x + d/den;
481 const Geom_Number y = __src.y + d*m/den;
500 const Geom_Number & m,
501 const Geom_Number & d)
502 :
Geom_Object(), src(__src), tgt(compute_tgt_point(src, m, d))
510 const Segment perp = sg.mid_perpendicular(dist);
512 const Point mid_point = sg.mid_point();
522 return compute_slope();
527 Geom_Number size()
const
529 return pitag(tgt.x - src.x, tgt.y - src.y);
533 bool is_colinear_with(
const Point & p)
const
539 bool is_to_left_from(
const Point & p)
const
545 bool is_to_right_from(
const Point & p)
const
551 Point mid_point()
const
553 const Geom_Number x = (src.
get_x() + tgt.
get_x()) / 2;
554 const Geom_Number y = (src.
get_y() + tgt.
get_y()) / 2;
562 const Point & nearest_point(
const Point & p)
const
571 Segment mid_perpendicular(
const Geom_Number & dist)
const
578 const Geom_Number arc_tgt_src = tgt_polar.get_theta();
582 Geom_Number arc_perp_pt = arctan(dist/(tgt_polar.get_r()/2));
584 const Geom_Number mperp = dist/(tgt_polar.get_r()/2);
587 Geom_Number perp_r = pitag(dist, tgt_polar.get_r()/2);
589 if (tgt_polar.get_r() < 0)
593 if (tgt_polar.get_theta() < 0)
594 arc_perp_pt = - arc_perp_pt;
599 const Polar_Point polar_perp_pt_l(perp_r, arc_tgt_src + arc_perp_pt);
603 const Polar_Point polar_perp_pt_r(perp_r, arc_tgt_src - arc_perp_pt);
611 if (p1.is_to_right_from(*
this))
621 bool intersects_properly_with(
const Segment & s)
const
635 bool contains_to(
const Point & p)
const
641 bool contains_to(
const Segment & s)
const
648 bool intersects_with(
const Segment & s)
const
650 if (this->intersects_properly_with(s))
656 return (this->contains_to(s.src) or this->contains_to(s.tgt) or
657 s.contains_to(this->src) or s.contains_to(this->tgt));
661 inline bool intersects_with(
const Triangle & t)
const;
664 inline bool intersects_with(
const Ellipse & e)
const;
667 bool is_parallel_with(
const Segment & s)
const
669 return slope() == s.slope();
682 if (this->is_parallel_with(s))
683 throw std::domain_error(
"Segments are parallels");
685 const Geom_Number & x1 = this->src.x;
686 const Geom_Number & y1 = this->src.y;
688 const Geom_Number & x2 = s.src.x;
689 const Geom_Number & y2 = s.src.y;
691 const Geom_Number & m1 = this->slope();
692 const Geom_Number & m2 = s.slope();
694 const Geom_Number x = (y2 - y1 + m1*x1 - m2*x2) / (m1 - m2);
696 const Geom_Number y = m1*(x - x1) + y1;
704 enum Sense { E, NE, N, NW, W, S, SW, SE };
712 else if (src.y > tgt.y)
722 else if (src.y > tgt.y)
729 return src.y > tgt.y ? N : S;
733 void enlarge_src(
const Geom_Number & __dist)
735 const double m = slope();
737 Point p = compute_tgt_point(src, m, - __dist);
741 if (s.size() < __dist)
742 p = compute_tgt_point(src, m, __dist);
748 void enlarge_tgt(
const Geom_Number & __dist)
750 const double m = slope();
752 Point p = compute_tgt_point(tgt, m, __dist);
756 if (s.size() < __dist)
757 p = compute_tgt_point(tgt, m, - __dist);
763 std::string to_string()
const
769 operator std::string ()
const
791 void rotate(
const double & angle)
799 tgt =
Polar_Point(ptgt.get_r(), ptgt.get_theta() + angle);
814 return s.contains_to(*
this);
846 Geom_Number dx = this->x - that.x;
847 Geom_Number dy = this->y - that.y;
848 return dx*dx + dy*dy;
880 : p1(__p1), p2(__p2), p3(__p3)
882 __area = area_of_parallelogram(p1, p2, p3)/2;
885 throw std::domain_error(
"The three points of triangle are colinears");
889 : p1(p), p2(s.src), p3(s.tgt)
891 __area = area_of_parallelogram(p1, p2, p3)/2;
894 throw std::domain_error(
"The three points of triangle are colinears");
898 : p1(s.src), p2(s.tgt), p3(p)
900 __area = area_of_parallelogram(p1, p2, p3)/2;
903 throw std::domain_error(
"The three points of triangle are colinears");
906 Geom_Number area()
const
912 bool is_clockwise()
const
919 const Point & max = p1.y > p2.y ? p1 : p2;
921 return p3.y > max.y ? p3 : max;
926 const Point & min = p1.y < p2.y ? p1 : p2;
928 return p3.y < min.y ? p3 : min;
933 const Point & min = p1.x < p2.x ? p1 : p2;
935 return p3.x < min.x ? p3 : min;
940 const Point & max = p1.x > p2.x ? p1 : p2;
942 return p3.x > max.x ? p3 : max;
945 const Point & get_p1()
const {
return p1; }
947 const Point & get_p2()
const {
return p2; }
949 const Point & get_p3()
const {
return p3; }
952 bool contains_to(
const Point & p)
const
968 return s.intersection_with(*
this);
974 Geom_Number xmin, ymin;
975 Geom_Number xmax, ymax;
979 const Geom_Number & get_xmin()
const {
return xmin; }
981 const Geom_Number & get_ymin()
const {
return ymin; }
983 const Geom_Number & get_xmax()
const {
return xmax; }
985 const Geom_Number & get_ymax()
const {
return ymax; }
987 Rectangle() : xmin(0), ymin(0), xmax(0), ymax(0)
992 Rectangle(
const Geom_Number & __xmin,
const Geom_Number & __ymin,
993 const Geom_Number & __xmax,
const Geom_Number & __ymax)
994 : xmin(__xmin), ymin(__ymin), xmax(__xmax), ymax(__ymax)
996 if (xmax < xmin || ymax < ymin)
997 throw std::range_error(
"Invalid rectangle");
1000 void set_rect(
const Geom_Number & xmin,
const Geom_Number & ymin,
1001 const Geom_Number & xmax,
const Geom_Number & ymax)
1003 new (
this)
Rectangle(xmin, ymin, xmax, ymax);
1006 Geom_Number width() {
return xmax - xmin; }
1008 Geom_Number height() {
return ymax - ymin; }
1013 return this->xmax >= that.xmin and this->ymax >= that.ymin and
1014 that.xmax >= this->xmin and that.ymax >= this->ymin;
1017 Geom_Number distance_squared_to(
const Point & p)
1019 Geom_Number dx = 0.0, dy = 0.0;
1020 if (p.
get_x() < xmin)
1021 dx = p.
get_x() - xmin;
1022 else if (p.
get_x() > xmax)
1023 dx = p.
get_x() - xmax;
1025 if (p.
get_y() < ymin)
1026 dy = p.
get_y() - ymin;
1027 else if (p.
get_y() > ymax)
1028 dy = p.
get_y() - ymax;
1030 return dx*dx + dy*dy;
1034 Geom_Number distance_to(
const Point & p)
1036 return sqrt(mpfr_class(distance_squared_to(p)));
1040 bool contains(
const Point & p)
const
1042 return p.
get_x() >= xmin and p.
get_x() <= xmax and
1051 inline bool Segment::intersects_with(
const Triangle & t)
const
1053 return (this->intersects_with(
Segment(t.get_p1(), t.get_p2())) or
1054 this->intersects_with(
Segment(t.get_p2(), t.get_p3())) or
1055 this->intersects_with(
Segment(t.get_p3(), t.get_p1())));
1066 if (not this->intersects_with(t))
1067 throw std::domain_error(
"segment does not intersects with triangle");
1075 p[i] = this->intersection_with(
Segment(t.get_p1(), t.get_p2()));
1077 if (t.contains_to(p[i]))
1080 catch (std::domain_error)
1087 p[i] = this->intersection_with(
Segment(t.get_p2(), t.get_p3()));
1089 if (t.contains_to(p[i]))
1092 catch (std::domain_error)
1103 p[i] = this->intersection_with(
Segment(t.get_p3(), t.get_p1()));
1105 catch (std::domain_error)
1145 const Geom_Number & __hr,
1146 const Geom_Number & __vr)
1147 : center(__center), hr(__hr), vr(__vr)
1153 :
Geom_Object(e), center(e.center), hr(e.hr), vr(e.vr)
1160 const Point & get_center()
const {
return center; }
1162 const Geom_Number & get_hradius()
const {
return hr; }
1164 const Geom_Number & get_vradius()
const {
return vr; }
1166 bool is_clockwise()
const {
return false; }
1170 return Point(center.get_x(), center.get_y() + vr);
1175 return Point(center.get_x(), center.get_y() - vr);
1180 return Point(center.get_x() - hr, center.get_y());
1185 return Point(center.get_x() + hr, center.get_y());
1211 compute_tangents(
Segment & s1,
Segment & s2,
const Geom_Number & m)
const
1221 const Geom_Number product = hr*hr*m*m + vr*vr;
1225 const Geom_Number y1= square_root(product);
1227 const Geom_Number x1 = -y1/m;
1244 const Geom_Number tangent_size = hr > vr ? hr : vr;
1248 const Geom_Number dsrc = center.distance_with(t1.
get_src_point());
1249 const Geom_Number dtgt = center.distance_with(t1.
get_tgt_point());
1254 s1.enlarge_src(tangent_size);
1259 s1.enlarge_tgt(tangent_size);
1265 const Geom_Number dsrc = center.distance_with(t2.
get_src_point());
1266 const Geom_Number dtgt = center.distance_with(t2.
get_tgt_point());
1271 s2.enlarge_src(tangent_size);
1276 s2.enlarge_tgt(tangent_size);
1287 compute_tangents(tg1, tg2, s.slope());
1305 Geom_Number compute_radius(
const Point & p)
const
1307 Geom_Number x2 = (p.
get_x() - center.get_x());
1310 Geom_Number y2 = (p.
get_y() - center.get_y());
1313 return x2/(hr*hr) + y2/(vr*vr);
1319 bool contains_to(
const Point & p)
const
1321 return compute_radius(p) <= 1;
1328 return compute_radius(p) == 1;
1394 throw std::domain_error(
"there is no intersection");
1396 const Geom_Number & a = hr;
1397 const Geom_Number & b = vr;
1399 const Geom_Number a2 = a*a;
1400 const Geom_Number b2 = b*b;
1402 const Geom_Number ab = a*b;
1408 const Point pr = sg_new.get_tgt_point();
1410 const Geom_Number & xr = pr.
get_x();
1411 const Geom_Number & yr = pr.get_y();
1413 const Geom_Number m = sg_new.slope();
1417 const Geom_Number m2 = m*m;
1419 const Geom_Number yr2 = yr*yr;
1421 const Geom_Number xr2 = xr*xr;
1423 I(m2 >= 0 and yr2 >= 0 and xr2 >= 0);
1425 const Geom_Number a2m2_plus_b2 = a2*m2 + b2;
1427 Geom_Number ab_root = -yr2 + 2*m*xr*yr -m2*xr2 + a2m2_plus_b2;
1428 ab_root = ab*square_root(ab_root);
1430 const Geom_Number ab_m_root = m*ab_root;
1432 const Geom_Number yr_minus_m_xr = yr - m*xr;
1434 const Geom_Number sumx = a2*m*yr_minus_m_xr;
1436 const Geom_Number sumy = b2*yr_minus_m_xr;
1440 const Geom_Number x1 = - (ab_root + sumx) / a2m2_plus_b2;
1442 const Geom_Number y1 = - (ab_m_root - sumy) / a2m2_plus_b2;
1444 const Geom_Number x2 = (ab_root - sumx) / a2m2_plus_b2;
1446 const Geom_Number y2 = (ab_m_root + sumy) / a2m2_plus_b2;
1461 return e.contains_to(*
this);
1467 return e.intersects_with(*
this);
1471 inline bool Segment::intersects_with(
const Ellipse & e)
const
1473 return e.intersects_with(*
this);
1478 inline Segment Segment::intersection_with(
const Ellipse & e)
const
1480 return e.intersection_with(*
this);
1498 inline size_t aproximate_string_size(
const std::string & str)
1500 const char * ptr = str.c_str();
1503 for (
int i = 0;
true; )
1509 for (++i; isalnum(ptr[i]) and ptr[i] !=
'\0'; )
1514 case '$':
case '{':
case '}':
case '\n':
1538 static const double font_width_in_points;
1540 static const double font_height_in_points;
1542 Text(
const Point & __p,
const std::string & __str)
1543 : p(__p), str(__str), __len(aproximate_string_size(__str))
1550 const size_t & len()
const {
return __len; }
1552 const Point & get_point()
const
1557 const std::string & get_str()
const {
return str; }
1581 area_of_parallelogram(
const Point & a,
const Point & b,
const Point & c)
Point & operator+=(const Point &p)
Definition: point.H:138
const Point & rightmost_point() const
Retorna el punto del segmento más al este.
Definition: point.H:431
bool is_clockwise_with(const Point &p1, const Point &p2) const
retorna true si la secuencia this-p1-p2 es en sentido horario
Definition: point.H:195
Point(const Geom_Number &__x, const Geom_Number &__y)
Constructor a partir de coordenadas __x e __y.
Definition: point.H:101
Polar_Point(const Point &p)
Constructor a partir de un punto cartesiano. El origen es (0,0)
Definition: point.H:305
const Point & nearest_point(const Point &p1, const Point &p2) const
retorna el punto más cercano a this entre p1 y p2
Definition: point.H:231
const Geom_Number & get_y() const
retorna el valor de la coordenada y
Definition: point.H:166
const Point & lowest_point() const
Retorna el punto del segmento más al sur.
Definition: point.H:419
const Geom_Number & get_x() const
retorna el valor de la coordenada x
Definition: point.H:161
std::string to_string() const
convierte el punto a un string de la forma "(x,y)"
Definition: point.H:246
const Geom_Number & get_r() const
Retorna la magnitud.
Definition: point.H:293
bool is_to_right_from(const Point &p1, const Point &p2) const
Definition: point.H:189
Segment(const Point &__src, const Geom_Number &m, const Geom_Number &d)
Definition: point.H:499
const Geom_Number & get_theta() const
retorna el ángulo
Definition: point.H:296
Point operator-(const Point &p) const
Resta de puntos. Útil para invertir resultado de la suma.
Definition: point.H:147
std::string to_string() const
Convierte a string.
Definition: point.H:356
bool is_to_left_from(const Point &p1, const Point &p2) const
Definition: point.H:182
bool operator==(const Point &point) const
Compara dos puntos retorna verdadero si son iguales.
Definition: point.H:117
bool operator!=(const Point &point) const
Compara dos puntos retorna verdadero si son distintos.
Definition: point.H:123
const Point & get_tgt_point() const
retorna el punto final del segmento
Definition: point.H:440
bool intersects_with(const Ellipse &e) const
retorna true si this intercepta con la elipse e
Definition: point.H:1465
Quadrant
Cuadrantes.
Definition: point.H:338
bool is_inside(const Segment &s) const
retorna true si this está contenido en el segmento s
Definition: point.H:812
const Point & leftmost_point() const
Retorna el punto del segmento más al oeste.
Definition: point.H:425
Geom_Number distance_with(const Point &p) const
retorna la distancia euclidiana entre this y el punto p
Definition: point.H:853
Point(const Point &p)
Contruye copia del punto p.
Definition: point.H:108
bool is_between(const Point &p1, const Point &p2) const
retorna true si this está contenido dentro del segmento p1–p2
Definition: point.H:210
Point & operator-=(const Point &p)
Resta de puntos. Útil para invertir resultado de la suma.
Definition: point.H:153
const Point & highest_point() const
Retorna el punto del segmento más al norte.
Definition: point.H:413
bool is_colinear_with(const Point &p1, const Point &p2) const
retorna true si this, p1 y p2 son colineales
Definition: point.H:172
Geom_Number distance_squared_to(const Point &that) const
retorna la distancia cuadrada entre this y that
Definition: point.H:844
const Point & get_src_point() const
retorna el punto inicial del segmento
Definition: point.H:437
Quadrant get_quadrant() const
Retorna el cuadrante donde se encuentra el punto.
Definition: point.H:341
Segment(const Point &__src, const Point &__tgt)
constructor fundamental dados los puntos origen y destino
Definition: point.H:451