38 # include <ahAssert.H> 43 typedef mpq_class Geom_Number;
45 inline double geom_number_to_double(
const Geom_Number & n)
50 inline std::ostream & operator << (std::ostream & o,
const Geom_Number & n)
60 const double PI = 3.1415926535897932384626433832795028841971693993751;
61 const double PI_2 = PI/2;
62 const double PI_4 = PI_2/2.0;
74 area_of_parallelogram(
const Point & a,
const Point & b,
const Point & c);
78 inline Geom_Number pitag(
const Geom_Number & x,
const Geom_Number & y)
80 return hypot(mpfr_class(x), mpfr_class(y));
83 inline Geom_Number arctan(
const Geom_Number & m)
85 return atan(mpfr_class(m));
88 inline Geom_Number arctan2(
const Geom_Number & m,
const Geom_Number & n)
90 return atan2(mpfr_class(m), mpfr_class(n));
93 inline Geom_Number sinus(
const Geom_Number & x)
95 return sin(mpfr_class(x));
98 inline Geom_Number cosinus(
const Geom_Number & x)
100 return cos(mpfr_class(x));
103 inline Geom_Number square_root(
const Geom_Number & x)
105 return sqrt(mpfr_class(x));
110 Geom_Object(
const Geom_Object & ) { }
114 virtual ~Geom_Object() { }
127 friend class Triangle;
135 Point() : Geom_Object(), x(0), y(0) { }
138 Point(
const Geom_Number & __x,
const Geom_Number & __y)
139 : Geom_Object(), x(__x), y(__y)
153 bool operator == (
const Point & point)
const 155 return x == point.x and y == point.y;
158 bool operator != (
const Point & point)
const 160 return not (*
this == point);
165 return Point(x + p.x, y + p.y);
178 return Point(x - p.x, y - p.y);
202 return area_of_parallelogram(*
this, p1, p2) == 0;
206 inline bool is_colinear_with(
const Segment & s)
const;
211 return area_of_parallelogram(p1, p2, *
this) > 0;
217 return area_of_parallelogram(p1, p2, *
this) < 0;
223 return not is_to_right_from(p1, p2);
229 return not is_to_left_from(p1, p2);
235 return area_of_parallelogram(*
this, p1, p2) < 0;
238 inline bool is_to_left_from(
const Segment & s)
const;
240 inline bool is_to_right_from(
const Segment & s)
const;
242 inline bool is_clockwise_with(
const Segment & s)
const;
247 if (not this->is_colinear_with(p1, p2))
251 return ((p1.
get_y() <= this->get_y()) and (this->get_y() <= p2.
get_y()))
252 or ((p1.
get_y() >= this->get_y()) and (this->get_y() >= p2.
get_y()));
254 return ((p1.
get_x() <= this->get_x()) and (this->get_x() <= p2.
get_x()))
255 or ((p1.
get_x() >= this->get_x()) and (this->get_x() >= p2.
get_x()));
261 return this->distance_with(p1) < this->distance_with(p2) ? p1 : p2;
265 inline bool is_inside(
const Segment & s)
const;
268 inline bool is_inside(
const Ellipse & e)
const;
271 inline bool intersects_with(
const Ellipse & e)
const;
276 return "(" + std::to_string(geom_number_to_double(x)) +
"," +
277 std::to_string(geom_number_to_double(y)) +
")";
284 inline Geom_Number distance_squared_to(
const Point & that)
const;
287 inline Geom_Number distance_with(
const Point & p)
const;
289 const Point & highest_point()
const {
return *
this; }
291 const Point & lowest_point()
const {
return *
this; }
293 const Point & leftmost_point()
const {
return *
this; }
295 const Point & rightmost_point()
const {
return *
this; }
298 extern const Point NullPoint;
318 const Geom_Number &
get_r()
const {
return r; }
323 Polar_Point(
const Geom_Number & __r,
const Geom_Number & __theta)
324 : r(__r), theta(__theta)
332 const Geom_Number & x = p.x;
333 const Geom_Number & y = p.y;
341 theta = y >= 0 ? PI/2 : 3*PI/2;
348 theta = x >= 0 ? 0 : PI;
368 if (r > 0 and theta > 0)
383 return "[" + std::to_string(geom_number_to_double(r)) +
"," +
384 std::to_string(geom_number_to_double(theta)) +
"]";
393 : x(pp.r * cosinus(pp.theta)), y(pp.r * sinus(pp.theta))
406 friend class Triangle;
410 double compute_slope()
const 415 return std::numeric_limits<double>::max();
417 return - std::numeric_limits<double>::max();
420 const Geom_Number __slope = (tgt.y - src.y) / (tgt.x - src.x);
422 return __slope.get_d();
427 bool operator == (
const Segment & s)
const 429 return src == s.src and tgt == s.tgt;
432 bool operator != (
const Segment & s)
const 434 return not (*
this == s);
437 const Point & highest_point()
const 439 return src.y > tgt.y ? src : tgt;
442 const Point & lowest_point()
const 444 return src.y < tgt.y ? src : tgt;
447 const Point & leftmost_point()
const 449 return src.x < tgt.x ? src : tgt;
452 const Point & rightmost_point()
const 454 return src.x > tgt.x ? src : tgt;
457 const Point & get_src_point()
const {
return src; }
459 const Point & get_tgt_point()
const {
return tgt; }
464 : Geom_Object(), src(s.src), tgt(s.tgt)
470 : Geom_Object(), src(__src), tgt(__tgt)
490 const Geom_Number & m,
491 const Geom_Number & d)
493 const Geom_Number den2 = 1 + m*m;
495 const Geom_Number den = square_root(den2);
497 const Geom_Number x = __src.x + d/den;
499 const Geom_Number y = __src.y + d*m/den;
518 const Geom_Number & m,
519 const Geom_Number & l)
520 : Geom_Object(), src(__src), tgt(compute_tgt_point(src, m, l))
528 const Segment perp = sg.mid_perpendicular(dist);
530 const Point mid_point = sg.mid_point();
532 const Point diff_point = mid_point - perp.get_src_point();
534 src = sg.get_src_point() + diff_point;
535 tgt = sg.get_tgt_point() + diff_point;
540 return compute_slope();
546 Geom_Number x1 = tgt.x - src.x;
547 Geom_Number x2 = s.tgt.x - s.src.x;
548 Geom_Number y1 = tgt.y - src.y;
549 Geom_Number y2 = s.tgt.y - s.src.y;
550 Geom_Number dot = x1 * x2 + y1 * y2;
551 Geom_Number det = x1 * y2 - y1 * x2;
553 Geom_Number angle = arctan2(det, dot);
559 return -angle.get_d();
561 return 2 * PI - angle.get_d();
568 return counterclockwise_angle_with(x_axis);
573 Geom_Number size()
const 575 return pitag(tgt.x - src.x, tgt.y - src.y);
597 Point mid_point()
const 599 const Geom_Number x = (src.
get_x() + tgt.
get_x()) / 2;
600 const Geom_Number y = (src.
get_y() + tgt.
get_y()) / 2;
630 Geom_Number m1 = Geom_Number(slope());
633 Geom_Number m2 = -Geom_Number(1.0) / m1;
638 const Geom_Number & x1 = src.
get_x();
639 const Geom_Number & y1 = src.
get_y();
640 const Geom_Number & x2 = p.
get_x();
641 const Geom_Number & y2 = p.
get_y();
643 Geom_Number x = (y2 - y1 + m1 * x1 - m2 * x2) / (m1 - m2);
644 Geom_Number y = m1 * (x - x1) + y1;
654 Segment mid_perpendicular(
const Geom_Number & dist)
const 661 const Geom_Number arc_tgt_src = tgt_polar.
get_theta();
665 Geom_Number arc_perp_pt = arctan(dist/(tgt_polar.
get_r()/2));
667 const Geom_Number mperp = dist/(tgt_polar.
get_r()/2);
670 Geom_Number perp_r = pitag(dist, tgt_polar.
get_r()/2);
672 if (tgt_polar.
get_r() < 0)
677 arc_perp_pt = - arc_perp_pt;
682 const Polar_Point polar_perp_pt_l(perp_r, arc_tgt_src + arc_perp_pt);
686 const Polar_Point polar_perp_pt_r(perp_r, arc_tgt_src - arc_perp_pt);
704 bool intersects_properly_with(
const Segment & s)
const 718 bool contains_to(
const Point & p)
const 724 bool contains_to(
const Segment & s)
const 726 return (s.get_src_point().
is_between(src, tgt) and
733 if (this->intersects_properly_with(s))
739 return (this->contains_to(s.src) or this->contains_to(s.tgt) or
740 s.contains_to(this->src) or s.contains_to(this->tgt));
750 bool is_parallel_with(
const Segment & s)
const 752 return slope() == s.slope();
765 if (this->is_parallel_with(s))
766 throw std::domain_error(
"Segments are parallels");
768 const Geom_Number & x1 = this->src.x;
769 const Geom_Number & y1 = this->src.y;
771 const Geom_Number & x2 = s.src.x;
772 const Geom_Number & y2 = s.src.y;
774 const Geom_Number & m1 = this->slope();
775 const Geom_Number & m2 = s.slope();
777 const Geom_Number x = (y2 - y1 + m1*x1 - m2*x2) / (m1 - m2);
779 const Geom_Number y = m1*(x - x1) + y1;
787 enum Sense { E, NE, N, NW, W, S, SW, SE };
795 else if (src.y > tgt.y)
805 else if (src.y > tgt.y)
812 return src.y > tgt.y ? N : S;
816 void enlarge_src(
const Geom_Number & __dist)
818 const double m = slope();
820 Point p = compute_tgt_point(src, m, - __dist);
824 if (s.size() < __dist)
825 p = compute_tgt_point(src, m, __dist);
831 void enlarge_tgt(
const Geom_Number & __dist)
833 const double m = slope();
835 Point p = compute_tgt_point(tgt, m, __dist);
839 if (s.size() < __dist)
840 p = compute_tgt_point(tgt, m, - __dist);
852 operator std::string ()
const 874 void rotate(
const double & angle)
888 inline Segment intersection_with(
const Triangle & t)
const;
891 inline Segment intersection_with(
const Ellipse & e)
const;
897 return s.contains_to(*
this);
929 Geom_Number dx = this->x - that.x;
930 Geom_Number dy = this->y - that.y;
931 return dx*dx + dy*dy;
951 class Triangle :
public Geom_Object
963 : p1(__p1), p2(__p2), p3(__p3)
965 __area = area_of_parallelogram(p1, p2, p3)/2;
968 throw std::domain_error(
"The three points of triangle are colinears");
972 : p1(p), p2(s.src), p3(s.tgt)
974 __area = area_of_parallelogram(p1, p2, p3)/2;
977 throw std::domain_error(
"The three points of triangle are colinears");
981 : p1(s.src), p2(s.tgt), p3(p)
983 __area = area_of_parallelogram(p1, p2, p3)/2;
986 throw std::domain_error(
"The three points of triangle are colinears");
989 Geom_Number area()
const 995 bool is_clockwise()
const 1000 const Point & highest_point()
const 1002 const Point & max = p1.y > p2.y ? p1 : p2;
1004 return p3.y > max.y ? p3 : max;
1007 const Point & lowest_point()
const 1009 const Point & min = p1.y < p2.y ? p1 : p2;
1011 return p3.y < min.y ? p3 : min;
1014 const Point & leftmost_point()
const 1016 const Point & min = p1.x < p2.x ? p1 : p2;
1018 return p3.x < min.x ? p3 : min;
1021 const Point & rightmost_point()
const 1023 const Point & max = p1.x > p2.x ? p1 : p2;
1025 return p3.x > max.x ? p3 : max;
1028 const Point & get_p1()
const {
return p1; }
1030 const Point & get_p2()
const {
return p2; }
1032 const Point & get_p3()
const {
return p3; }
1035 bool contains_to(
const Point & p)
const 1051 return s.intersection_with(*
this);
1057 Geom_Number xmin, ymin;
1058 Geom_Number xmax, ymax;
1062 const Geom_Number & get_xmin()
const {
return xmin; }
1064 const Geom_Number & get_ymin()
const {
return ymin; }
1066 const Geom_Number & get_xmax()
const {
return xmax; }
1068 const Geom_Number & get_ymax()
const {
return ymax; }
1070 Rectangle() : xmin(0), ymin(0), xmax(0), ymax(0)
1075 Rectangle(
const Geom_Number & __xmin,
const Geom_Number & __ymin,
1076 const Geom_Number & __xmax,
const Geom_Number & __ymax)
1077 : xmin(__xmin), ymin(__ymin), xmax(__xmax), ymax(__ymax)
1079 if (xmax < xmin || ymax < ymin)
1080 throw std::range_error(
"Invalid rectangle");
1083 void set_rect(
const Geom_Number & xmin,
const Geom_Number & ymin,
1084 const Geom_Number & xmax,
const Geom_Number & ymax)
1086 new (
this) Rectangle(xmin, ymin, xmax, ymax);
1089 Geom_Number width() {
return xmax - xmin; }
1091 Geom_Number height() {
return ymax - ymin; }
1094 bool intersects(
const Rectangle & that)
1096 return this->xmax >= that.xmin and this->ymax >= that.ymin and
1097 that.xmax >= this->xmin and that.ymax >= this->ymin;
1102 Geom_Number dx = 0.0, dy = 0.0;
1103 if (p.
get_x() < xmin)
1104 dx = p.
get_x() - xmin;
1105 else if (p.
get_x() > xmax)
1106 dx = p.
get_x() - xmax;
1108 if (p.
get_y() < ymin)
1109 dy = p.
get_y() - ymin;
1110 else if (p.
get_y() > ymax)
1111 dy = p.
get_y() - ymax;
1113 return dx*dx + dy*dy;
1117 Geom_Number distance_to(
const Point & p)
1123 bool contains(
const Point & p)
const 1125 return p.
get_x() >= xmin and p.
get_x() <= xmax and
1134 inline bool Segment::intersects_with(
const Triangle & t)
const 1147 inline Segment Segment::intersection_with(
const Triangle & t)
const 1150 throw std::domain_error(
"segment does not intersects with triangle");
1158 p[i] = this->intersection_with(
Segment(t.get_p1(), t.get_p2()));
1160 if (t.contains_to(p[i]))
1163 catch (std::domain_error)
1170 p[i] = this->intersection_with(
Segment(t.get_p2(), t.get_p3()));
1172 if (t.contains_to(p[i]))
1175 catch (std::domain_error)
1186 p[i] = this->intersection_with(
Segment(t.get_p3(), t.get_p1()));
1188 catch (std::domain_error)
1205 class Ellipse :
public Geom_Object
1227 Ellipse(
const Point & __center,
1228 const Geom_Number & __hr,
1229 const Geom_Number & __vr)
1230 : center(__center), hr(__hr), vr(__vr)
1235 Ellipse(
const Ellipse & e)
1236 : Geom_Object(e), center(e.center), hr(e.hr), vr(e.vr)
1243 const Point & get_center()
const {
return center; }
1245 const Geom_Number & get_hradius()
const {
return hr; }
1247 const Geom_Number & get_vradius()
const {
return vr; }
1249 bool is_clockwise()
const {
return false; }
1251 Point highest_point()
const 1256 Point lowest_point()
const 1261 Point leftmost_point()
const 1266 Point rightmost_point()
const 1294 compute_tangents(
Segment & s1,
Segment & s2,
const Geom_Number & m)
const 1304 const Geom_Number product = hr*hr*m*m + vr*vr;
1308 const Geom_Number y1= square_root(product);
1310 const Geom_Number x1 = -y1/m;
1327 const Geom_Number tangent_size = hr > vr ? hr : vr;
1331 const Geom_Number dsrc = center.
distance_with(t1.get_src_point());
1332 const Geom_Number dtgt = center.
distance_with(t1.get_tgt_point());
1336 s1 =
Segment(t1.get_src_point(), m, tangent_size);
1337 s1.enlarge_src(tangent_size);
1341 s1 =
Segment(t1.get_tgt_point(), m, tangent_size);
1342 s1.enlarge_tgt(tangent_size);
1348 const Geom_Number dsrc = center.
distance_with(t2.get_src_point());
1349 const Geom_Number dtgt = center.
distance_with(t2.get_tgt_point());
1353 s2 =
Segment(t2.get_src_point(), m, tangent_size);
1354 s2.enlarge_src(tangent_size);
1358 s2 =
Segment(t2.get_tgt_point(), m, tangent_size);
1359 s2.enlarge_tgt(tangent_size);
1370 compute_tangents(tg1, tg2, s.slope());
1374 return (s.is_to_left_from(tg1.get_src_point()) xor
1375 s.is_to_left_from(tg2.get_tgt_point()));
1388 Geom_Number compute_radius(
const Point & p)
const 1390 Geom_Number x2 = (p.
get_x() - center.
get_x());
1393 Geom_Number y2 = (p.
get_y() - center.
get_y());
1396 return x2/(hr*hr) + y2/(vr*vr);
1402 bool contains_to(
const Point & p)
const 1404 return compute_radius(p) <= 1;
1411 return compute_radius(p) == 1;
1477 throw std::domain_error(
"there is no intersection");
1479 const Geom_Number & a = hr;
1480 const Geom_Number & b = vr;
1482 const Geom_Number a2 = a*a;
1483 const Geom_Number b2 = b*b;
1485 const Geom_Number ab = a*b;
1488 const Segment sg_new(sg.get_src_point() - center,
1489 sg.get_tgt_point() - center);
1491 const Point pr = sg_new.get_tgt_point();
1493 const Geom_Number & xr = pr.
get_x();
1494 const Geom_Number & yr = pr.get_y();
1496 const Geom_Number m = sg_new.slope();
1498 assert(m == sg.slope());
1500 const Geom_Number m2 = m*m;
1502 const Geom_Number yr2 = yr*yr;
1504 const Geom_Number xr2 = xr*xr;
1506 assert(m2 >= 0 and yr2 >= 0 and xr2 >= 0);
1508 const Geom_Number a2m2_plus_b2 = a2*m2 + b2;
1510 Geom_Number ab_root = -yr2 + 2*m*xr*yr -m2*xr2 + a2m2_plus_b2;
1511 ab_root = ab*square_root(ab_root);
1513 const Geom_Number ab_m_root = m*ab_root;
1515 const Geom_Number yr_minus_m_xr = yr - m*xr;
1517 const Geom_Number sumx = a2*m*yr_minus_m_xr;
1519 const Geom_Number sumy = b2*yr_minus_m_xr;
1523 const Geom_Number x1 = - (ab_root + sumx) / a2m2_plus_b2;
1525 const Geom_Number y1 = - (ab_m_root - sumy) / a2m2_plus_b2;
1527 const Geom_Number x2 = (ab_root - sumx) / a2m2_plus_b2;
1529 const Geom_Number y2 = (ab_m_root + sumy) / a2m2_plus_b2;
1544 return e.contains_to(*
this);
1550 return e.intersects_with(*
this);
1554 inline bool Segment::intersects_with(
const Ellipse & e)
const 1556 return e.intersects_with(*
this);
1561 inline Segment Segment::intersection_with(
const Ellipse & e)
const 1563 return e.intersection_with(*
this);
1581 inline size_t aproximate_string_size(
const std::string & str)
1583 const char * ptr = str.c_str();
1586 for (
int i = 0;
true; )
1592 for (++i; isalnum(ptr[i]) and ptr[i] !=
'\0'; )
1597 case '$':
case '{':
case '}':
case '\n':
1611 class Text :
public Geom_Object
1621 static const double font_width_in_points;
1623 static const double font_height_in_points;
1625 Text(
const Point & __p,
const std::string & __str)
1626 : p(__p), str(__str), __len(aproximate_string_size(__str))
1633 const size_t & len()
const {
return __len; }
1635 const Point & get_point()
const 1640 const std::string & get_str()
const {
return str; }
1642 Point highest_point()
const 1647 Point lowest_point()
const 1652 Point leftmost_point()
const 1657 Point rightmost_point()
const 1664 area_of_parallelogram(
const Point & a,
const Point & b,
const Point & c)
Geom_Number distance_with(const Point &p) const
Returns the euclidean distance between this and p.
Definition: point.H:936
double counterclockwise_angle() const
Compute the counterclock angle of this respect x-axis.
Definition: point.H:565
const Geom_Number & get_theta() const
Returns the angle.
Definition: point.H:321
bool is_clockwise_with(const Point &p1, const Point &p2) const
Returns true if the sequence this-p1-p2 is clockwise.
Definition: point.H:233
Point(const Geom_Number &__x, const Geom_Number &__y)
Builds a new point in coordinates (__x, __y)
Definition: point.H:138
Geom_Number distance_squared_to(const Point &that) const
Returns the square distance between this y that.
Definition: point.H:927
std::string to_string() const
Convierte a string.
Definition: point.H:381
Quadrant get_quadrant() const
Retorna el cuadrante donde se encuentra el punto.
Definition: point.H:366
Polar_Point(const Point &p)
Constructor a partir de un punto cartesiano. El origen es (0,0)
Definition: point.H:330
bool is_to_right_on_from(const Point &p1, const Point &p2) const
Return true if this is to right from (or on) points p1 and p2.
Definition: point.H:227
bool is_inside(const Segment &s) const
Returns true if this is inside of segment s.
Definition: point.H:895
bool is_to_left_on_from(const Point &p1, const Point &p2) const
Return true if this is to left from (or on) points p1 and p2.
Definition: point.H:221
Segment(const Segment &sg, const Geom_Number &dist)
Builds a new segment parallel to sg and with a distance dist.
Definition: point.H:526
const Point & nearest_point(const Point &p1, const Point &p2) const
Return the nearest point (to this) between p1 and p2.
Definition: point.H:259
Segment(const Point &__src, const Geom_Number &m, const Geom_Number &l)
Definition: point.H:517
bool is_colinear_with(const Point &p1, const Point &p2) const
Returns true if this is colinear with p1 and p2.
Definition: point.H:200
std::string to_string() const
Return a string representation of this.
Definition: point.H:274
bool is_to_right_from(const Point &p1, const Point &p2) const
Return true if this is to right from points p1 and p2.
Definition: point.H:215
double counterclockwise_angle_with(const Segment &s) const
Compute the counterclock wise angle respect another segment s.
Definition: point.H:544
Quadrant
Cuadrantes.
Definition: point.H:363
const Geom_Number & get_x() const
Returns x value.
Definition: point.H:189
bool is_to_left_from(const Point &p1, const Point &p2) const
Return true if this is to left from points p1 and p2.
Definition: point.H:209
bool intersects_with(const Ellipse &e) const
retorna true si this intercepta con la elipse e
Definition: point.H:1548
Point(const Point &p)
Builds a copy of p.
Definition: point.H:145
bool is_between(const Point &p1, const Point &p2) const
Returns true if this is between p1 and p2.
Definition: point.H:245
const Geom_Number & get_y() const
Returns y value.
Definition: point.H:194
const Geom_Number & get_r() const
Returns the magnitude.
Definition: point.H:318