File indexing completed on 2025-01-18 09:48:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_POLYGON_SEGMENT_CONCEPT_HPP
0013 #define BOOST_POLYGON_SEGMENT_CONCEPT_HPP
0014
0015 #include "isotropy.hpp"
0016 #include "segment_traits.hpp"
0017 #include "rectangle_concept.hpp"
0018
0019 namespace boost {
0020 namespace polygon {
0021
0022 struct segment_concept {};
0023
0024 template <typename ConceptType>
0025 struct is_segment_concept {
0026 typedef gtl_no type;
0027 };
0028
0029 template <>
0030 struct is_segment_concept<segment_concept> {
0031 typedef gtl_yes type;
0032 };
0033
0034 template <typename ConceptType>
0035 struct is_mutable_segment_concept {
0036 typedef gtl_no type;
0037 };
0038
0039 template <>
0040 struct is_mutable_segment_concept<segment_concept> {
0041 typedef gtl_yes type;
0042 };
0043
0044 template <typename GeometryType, typename BoolType>
0045 struct segment_distance_type_by_concept {
0046 typedef void type;
0047 };
0048
0049 template <typename GeometryType>
0050 struct segment_distance_type_by_concept<GeometryType, gtl_yes> {
0051 typedef typename coordinate_traits<
0052 typename segment_traits<GeometryType>::coordinate_type
0053 >::coordinate_distance type;
0054 };
0055
0056 template <typename GeometryType>
0057 struct segment_distance_type {
0058 typedef typename segment_distance_type_by_concept<
0059 GeometryType,
0060 typename is_segment_concept<
0061 typename geometry_concept<GeometryType>::type
0062 >::type
0063 >::type type;
0064 };
0065
0066 template <typename GeometryType, typename BoolType>
0067 struct segment_point_type_by_concept {
0068 typedef void type;
0069 };
0070
0071 template <typename GeometryType>
0072 struct segment_point_type_by_concept<GeometryType, gtl_yes> {
0073 typedef typename segment_traits<GeometryType>::point_type type;
0074 };
0075
0076 template <typename GeometryType>
0077 struct segment_point_type {
0078 typedef typename segment_point_type_by_concept<
0079 GeometryType,
0080 typename is_segment_concept<
0081 typename geometry_concept<GeometryType>::type
0082 >::type
0083 >::type type;
0084 };
0085
0086 template <typename GeometryType, typename BoolType>
0087 struct segment_coordinate_type_by_concept {
0088 typedef void type;
0089 };
0090
0091 template <typename GeometryType>
0092 struct segment_coordinate_type_by_concept<GeometryType, gtl_yes> {
0093 typedef typename segment_traits<GeometryType>::coordinate_type type;
0094 };
0095
0096 template <typename GeometryType>
0097 struct segment_coordinate_type {
0098 typedef typename segment_coordinate_type_by_concept<
0099 GeometryType,
0100 typename is_segment_concept<
0101 typename geometry_concept<GeometryType>::type
0102 >::type
0103 >::type type;
0104 };
0105
0106 struct y_s_get : gtl_yes {};
0107
0108 template <typename Segment>
0109 typename enable_if<
0110 typename gtl_and<
0111 y_s_get,
0112 typename is_segment_concept<
0113 typename geometry_concept<Segment>::type
0114 >::type
0115 >::type,
0116 typename segment_point_type<Segment>::type>::type
0117 get(const Segment& segment, direction_1d dir) {
0118 return segment_traits<Segment>::get(segment, dir);
0119 }
0120
0121 struct y_s_set : gtl_yes {};
0122
0123 template <typename Segment, typename Point>
0124 typename enable_if<
0125 typename gtl_and_3<
0126 y_s_set,
0127 typename is_mutable_segment_concept<
0128 typename geometry_concept<Segment>::type
0129 >::type,
0130 typename is_point_concept<
0131 typename geometry_concept<Point>::type
0132 >::type
0133 >::type,
0134 void>::type set(Segment& segment, direction_1d dir, const Point& point) {
0135 segment_mutable_traits<Segment>::set(segment, dir, point);
0136 }
0137
0138 struct y_s_construct : gtl_yes {};
0139
0140 template <typename Segment, typename Point1, typename Point2>
0141 typename enable_if<
0142 typename gtl_and_4<
0143 y_s_construct,
0144 typename is_mutable_segment_concept<
0145 typename geometry_concept<Segment>::type
0146 >::type,
0147 typename is_point_concept<
0148 typename geometry_concept<Point1>::type
0149 >::type,
0150 typename is_point_concept<
0151 typename geometry_concept<Point2>::type
0152 >::type
0153 >::type,
0154 Segment>::type construct(const Point1& low, const Point2& high) {
0155 return segment_mutable_traits<Segment>::construct(low, high);
0156 }
0157
0158 struct y_s_copy_construct : gtl_yes {};
0159
0160 template <typename Segment1, typename Segment2>
0161 typename enable_if<
0162 typename gtl_and_3<
0163 y_s_copy_construct,
0164 typename is_mutable_segment_concept<
0165 typename geometry_concept<Segment1>::type
0166 >::type,
0167 typename is_segment_concept<
0168 typename geometry_concept<Segment2>::type
0169 >::type
0170 >::type,
0171 Segment1>::type copy_construct(const Segment2& segment) {
0172 return construct<Segment1>(get(segment, LOW), get(segment, HIGH));
0173 }
0174
0175 struct y_s_assign : gtl_yes {};
0176
0177 template <typename Segment1, typename Segment2>
0178 typename enable_if<
0179 typename gtl_and_3<
0180 y_s_assign,
0181 typename is_mutable_segment_concept<
0182 typename geometry_concept<Segment1>::type
0183 >::type,
0184 typename is_segment_concept<
0185 typename geometry_concept<Segment2>::type
0186 >::type
0187 >::type,
0188 Segment1>::type& assign(Segment1& segment1, const Segment2& segment2) {
0189 return segment1 = copy_construct<Segment1>(segment2);
0190 }
0191
0192 struct y_s_equivalence : gtl_yes {};
0193
0194 template <typename Segment1, typename Segment2>
0195 typename enable_if<
0196 typename gtl_and_3<
0197 y_s_equivalence,
0198 typename is_segment_concept<
0199 typename geometry_concept<Segment1>::type
0200 >::type,
0201 typename is_segment_concept<
0202 typename geometry_concept<Segment2>::type
0203 >::type
0204 >::type,
0205 bool>::type equivalence(const Segment1& segment1, const Segment2& segment2) {
0206 return get(segment1, LOW) == get(segment2, LOW) &&
0207 get(segment1, HIGH) == get(segment2, HIGH);
0208 }
0209
0210 struct y_s_low : gtl_yes {};
0211
0212 template <typename Segment>
0213 typename enable_if<
0214 typename gtl_and<
0215 y_s_low,
0216 typename is_segment_concept<
0217 typename geometry_concept<Segment>::type
0218 >::type
0219 >::type,
0220 typename segment_point_type<Segment>::type>::type low(const Segment& segment) {
0221 return get(segment, LOW);
0222 }
0223
0224 struct y_s_high : gtl_yes {};
0225
0226 template <typename Segment>
0227 typename enable_if<
0228 typename gtl_and<
0229 y_s_high,
0230 typename is_segment_concept<
0231 typename geometry_concept<Segment>::type
0232 >::type
0233 >::type,
0234 typename segment_point_type<Segment>::type>::type high(const Segment& segment) {
0235 return get(segment, HIGH);
0236 }
0237
0238 struct y_s_center : gtl_yes {};
0239
0240 template <typename Segment>
0241 typename enable_if<
0242 typename gtl_and<
0243 y_s_center,
0244 typename is_segment_concept<
0245 typename geometry_concept<Segment>::type
0246 >::type
0247 >::type,
0248 typename segment_point_type<Segment>::type>::type
0249 center(const Segment& segment) {
0250 return construct<typename segment_point_type<Segment>::type>(
0251 (x(high(segment)) + x(low(segment)))/2,
0252 (y(high(segment)) + y(low(segment)))/2);
0253 }
0254
0255 struct y_s_low2 : gtl_yes {};
0256
0257 template <typename Segment, typename Point>
0258 typename enable_if<
0259 typename gtl_and_3<
0260 y_s_low2,
0261 typename is_mutable_segment_concept<
0262 typename geometry_concept<Segment>::type
0263 >::type,
0264 typename is_point_concept<
0265 typename geometry_concept<Point>::type
0266 >::type
0267 >::type,
0268 void>::type low(Segment& segment, const Point& point) {
0269 set(segment, LOW, point);
0270 }
0271
0272 struct y_s_high2 : gtl_yes {};
0273
0274 template <typename Segment, typename Point>
0275 typename enable_if<
0276 typename gtl_and_3<
0277 y_s_high2,
0278 typename is_mutable_segment_concept<
0279 typename geometry_concept<Segment>::type
0280 >::type,
0281 typename is_point_concept<
0282 typename geometry_concept<Point>::type
0283 >::type
0284 >::type,
0285 void>::type high(Segment& segment, const Point& point) {
0286 set(segment, HIGH, point);
0287 }
0288
0289 struct y_s_orientation1 : gtl_yes {};
0290
0291
0292 template <typename Segment1, typename Segment2>
0293 typename enable_if<
0294 typename gtl_and_3<
0295 y_s_orientation1,
0296 typename is_segment_concept<
0297 typename geometry_concept<Segment1>::type
0298 >::type,
0299 typename is_segment_concept<
0300 typename geometry_concept<Segment2>::type
0301 >::type
0302 >::type,
0303 int>::type orientation(const Segment1& segment1, const Segment2& segment2) {
0304 typedef typename coordinate_traits<
0305 typename segment_traits<Segment1>::coordinate_type
0306 >::manhattan_area_type int_x2;
0307 typedef typename coordinate_traits<
0308 typename segment_traits<Segment1>::coordinate_type
0309 >::unsigned_area_type uint_x2;
0310 int_x2 a1 = (int_x2)x(high(segment1)) - (int_x2)x(low(segment1));
0311 int_x2 b1 = (int_x2)y(high(segment1)) - (int_x2)y(low(segment1));
0312 int_x2 a2 = (int_x2)x(high(segment2)) - (int_x2)x(low(segment2));
0313 int_x2 b2 = (int_x2)y(high(segment2)) - (int_x2)y(low(segment2));
0314
0315 int sign1 = 0;
0316 int sign2 = 0;
0317 if (a1 && b2)
0318 sign1 = ((a1 > 0) ^ (b2 > 0)) ? -1 : 1;
0319 if (a2 && b1)
0320 sign2 = ((a2 > 0) ^ (b1 > 0)) ? -1 : 1;
0321
0322 if (sign1 != sign2)
0323 return (sign1 < sign2) ? -1 : 1;
0324 uint_x2 a3 = (uint_x2)(a1 < 0 ? -a1 : a1) * (uint_x2)(b2 < 0 ? -b2 : b2);
0325 uint_x2 b3 = (uint_x2)(b1 < 0 ? -b1 : b1) * (uint_x2)(a2 < 0 ? -a2 : a2);
0326 if (a3 == b3)
0327 return 0;
0328 return ((a3 < b3) ^ (sign1 == 1)) ? 1 : -1;
0329 }
0330
0331 struct y_s_orientation2 : gtl_yes {};
0332
0333
0334 template <typename Segment, typename Point>
0335 typename enable_if<
0336 typename gtl_and_3<
0337 y_s_orientation2,
0338 typename is_segment_concept<
0339 typename geometry_concept<Segment>::type
0340 >::type,
0341 typename is_point_concept<
0342 typename geometry_concept<Point>::type
0343 >::type
0344 >::type,
0345 int>::type orientation(const Segment& segment, const Point& point) {
0346 Segment segment2 = construct<Segment>(high(segment), point);
0347 return orientation(segment, segment2);
0348 }
0349
0350 struct y_s_contains : gtl_yes {};
0351
0352 template <typename Segment, typename Point>
0353 typename enable_if<
0354 typename gtl_and_3<
0355 y_s_contains,
0356 typename is_segment_concept<
0357 typename geometry_concept<Segment>::type
0358 >::type,
0359 typename is_point_concept<
0360 typename geometry_concept<Point>::type
0361 >::type
0362 >::type,
0363 bool>::type contains(const Segment& segment,
0364 const Point& point, bool consider_touch = true ) {
0365 if (orientation(segment, point))
0366 return false;
0367 rectangle_data<typename segment_coordinate_type<Segment>::type> rect;
0368 set_points(rect, low(segment), high(segment));
0369 if (!contains(rect, point, true))
0370 return false;
0371 if (!consider_touch &&
0372 (equivalence(low(segment), point) ||
0373 equivalence(high(segment), point)))
0374 return false;
0375 return true;
0376 }
0377
0378 struct y_s_contains2 : gtl_yes {};
0379
0380 template <typename Segment1, typename Segment2>
0381 typename enable_if<
0382 typename gtl_and_3<
0383 y_s_contains2,
0384 typename is_segment_concept<
0385 typename geometry_concept<Segment1>::type
0386 >::type,
0387 typename is_segment_concept<
0388 typename geometry_concept<Segment2>::type
0389 >::type
0390 >::type,
0391 bool>::type contains(const Segment1& segment1,
0392 const Segment2& segment2, bool consider_touch = true) {
0393 return contains(segment1, get(segment2, LOW), consider_touch) &&
0394 contains(segment1, get(segment2, HIGH), consider_touch);
0395 }
0396
0397 struct y_s_length : gtl_yes {};
0398
0399 template <typename Segment>
0400 typename enable_if<
0401 typename gtl_and<
0402 y_s_length,
0403 typename is_segment_concept<
0404 typename geometry_concept<Segment>::type
0405 >::type
0406 >::type,
0407 typename segment_distance_type<Segment>::type>::type
0408 length(const Segment& segment) {
0409 return euclidean_distance(low(segment), high(segment));
0410 }
0411
0412 struct y_s_scale_up : gtl_yes {};
0413
0414 template <typename Segment>
0415 typename enable_if<
0416 typename gtl_and<
0417 y_s_scale_up,
0418 typename is_mutable_segment_concept<
0419 typename geometry_concept<Segment>::type
0420 >::type
0421 >::type,
0422 Segment>::type& scale_up(Segment& segment,
0423 typename coordinate_traits<
0424 typename segment_coordinate_type<Segment>::type
0425 >::unsigned_area_type factor) {
0426 typename segment_point_type<Segment>::type l = low(segment);
0427 typename segment_point_type<Segment>::type h = high(segment);
0428 low(segment, scale_up(l, factor));
0429 high(segment, scale_up(h, factor));
0430 return segment;
0431 }
0432
0433 struct y_s_scale_down : gtl_yes {};
0434
0435 template <typename Segment>
0436 typename enable_if<
0437 typename gtl_and<
0438 y_s_scale_down,
0439 typename is_mutable_segment_concept<
0440 typename geometry_concept<Segment>::type
0441 >::type
0442 >::type,
0443 Segment>::type& scale_down(Segment& segment,
0444 typename coordinate_traits<
0445 typename segment_coordinate_type<Segment>::type
0446 >::unsigned_area_type factor) {
0447 typename segment_point_type<Segment>::type l = low(segment);
0448 typename segment_point_type<Segment>::type h = high(segment);
0449 low(segment, scale_down(l, factor));
0450 high(segment, scale_down(h, factor));
0451 return segment;
0452 }
0453
0454 struct y_s_scale : gtl_yes {};
0455
0456 template <typename Segment, typename Scale>
0457 typename enable_if<
0458 typename gtl_and<
0459 y_s_scale,
0460 typename is_mutable_segment_concept<
0461 typename geometry_concept<Segment>::type
0462 >::type
0463 >::type,
0464 Segment>::type& scale(Segment& segment, const Scale& sc) {
0465 typename segment_point_type<Segment>::type l = low(segment);
0466 typename segment_point_type<Segment>::type h = high(segment);
0467 low(segment, scale(l, sc));
0468 high(segment, scale(h, sc));
0469 return segment;
0470 }
0471
0472 struct y_s_transform : gtl_yes {};
0473
0474 template <typename Segment, typename Transform>
0475 typename enable_if<
0476 typename gtl_and<
0477 y_s_transform,
0478 typename is_mutable_segment_concept<
0479 typename geometry_concept<Segment>::type
0480 >::type
0481 >::type,
0482 Segment>::type& transform(Segment& segment, const Transform& tr) {
0483 typename segment_point_type<Segment>::type l = low(segment);
0484 typename segment_point_type<Segment>::type h = high(segment);
0485 low(segment, transform(l, tr));
0486 high(segment, transform(h, tr));
0487 return segment;
0488 }
0489
0490 struct y_s_move : gtl_yes {};
0491
0492 template <typename Segment>
0493 typename enable_if<
0494 typename gtl_and<
0495 y_s_move,
0496 typename is_mutable_segment_concept<
0497 typename geometry_concept<Segment>::type
0498 >::type
0499 >::type,
0500 Segment>::type& move(Segment& segment, orientation_2d orient,
0501 typename segment_coordinate_type<Segment>::type displacement) {
0502 typename segment_point_type<Segment>::type l = low(segment);
0503 typename segment_point_type<Segment>::type h = high(segment);
0504 low(segment, move(l, orient, displacement));
0505 high(segment, move(h, orient, displacement));
0506 return segment;
0507 }
0508
0509 struct y_s_convolve : gtl_yes {};
0510
0511 template <typename Segment, typename Point>
0512 typename enable_if<
0513 typename gtl_and_3<
0514 y_s_convolve,
0515 typename is_mutable_segment_concept<
0516 typename geometry_concept<Segment>::type
0517 >::type,
0518 typename is_point_concept<
0519 typename geometry_concept<Point>::type
0520 >::type
0521 >::type,
0522 Segment>::type& convolve(Segment& segment, const Point& point) {
0523 typename segment_point_type<Segment>::type l = low(segment);
0524 typename segment_point_type<Segment>::type h = high(segment);
0525 low(segment, convolve(l, point));
0526 high(segment, convolve(h, point));
0527 return segment;
0528 }
0529
0530 struct y_s_deconvolve : gtl_yes {};
0531
0532 template <typename Segment, typename Point>
0533 typename enable_if<
0534 typename gtl_and_3<
0535 y_s_deconvolve,
0536 typename is_mutable_segment_concept<
0537 typename geometry_concept<Segment>::type
0538 >::type,
0539 typename is_point_concept<
0540 typename geometry_concept<Point>::type
0541 >::type
0542 >::type,
0543 Segment>::type& deconvolve(Segment& segment, const Point& point) {
0544 typename segment_point_type<Segment>::type l = low(segment);
0545 typename segment_point_type<Segment>::type h = high(segment);
0546 low(segment, deconvolve(l, point));
0547 high(segment, deconvolve(h, point));
0548 return segment;
0549 }
0550
0551 struct y_s_abuts1 : gtl_yes {};
0552
0553 template <typename Segment1, typename Segment2>
0554 typename enable_if<
0555 typename gtl_and_3<
0556 y_s_abuts1,
0557 typename is_segment_concept<
0558 typename geometry_concept<Segment1>::type
0559 >::type,
0560 typename is_segment_concept<
0561 typename geometry_concept<Segment2>::type
0562 >::type
0563 >::type,
0564 bool>::type abuts(const Segment1& segment1,
0565 const Segment2& segment2, direction_1d dir) {
0566 return dir.to_int() ? equivalence(low(segment2) , high(segment1)) :
0567 equivalence(low(segment1) , high(segment2));
0568 }
0569
0570 struct y_s_abuts2 : gtl_yes {};
0571
0572 template <typename Segment1, typename Segment2>
0573 typename enable_if<
0574 typename gtl_and_3<
0575 y_s_abuts2,
0576 typename is_segment_concept<
0577 typename geometry_concept<Segment1>::type
0578 >::type,
0579 typename is_segment_concept<
0580 typename geometry_concept<Segment2>::type
0581 >::type
0582 >::type,
0583 bool>::type abuts(const Segment1& segment1, const Segment2& segment2) {
0584 return abuts(segment1, segment2, HIGH) || abuts(segment1, segment2, LOW);
0585 }
0586
0587 struct y_s_e_intersects : gtl_yes {};
0588
0589 template <typename Segment1, typename Segment2>
0590 typename enable_if<
0591 typename gtl_and_3<
0592 y_s_e_intersects,
0593 typename is_segment_concept<
0594 typename geometry_concept<Segment1>::type
0595 >::type,
0596 typename is_segment_concept<
0597 typename geometry_concept<Segment2>::type
0598 >::type
0599 >::type,
0600 bool
0601 >::type intersects(const Segment1& segment1, const Segment2& segment2,
0602 bool consider_touch = true) {
0603 rectangle_data<typename segment_coordinate_type<Segment1>::type> rect1, rect2;
0604 set_points(rect1, low(segment1), high(segment1));
0605 set_points(rect2, low(segment2), high(segment2));
0606
0607 if (!intersects(rect1, rect2, true))
0608 return false;
0609 int or1_1 = orientation(segment1, low(segment2));
0610 int or1_2 = orientation(segment1, high(segment2));
0611 if (or1_1 * or1_2 > 0)
0612 return false;
0613 int or2_1 = orientation(segment2, low(segment1));
0614 int or2_2 = orientation(segment2, high(segment1));
0615 if (or2_1 * or2_2 > 0)
0616 return false;
0617 if (consider_touch || (or1_1 && or1_2) || (or2_1 && or2_2))
0618 return true;
0619 if (or1_1 || or1_2)
0620 return false;
0621 return intersects(vertical(rect1), vertical(rect2), false) ||
0622 intersects(horizontal(rect1), horizontal(rect2), false);
0623 }
0624
0625 struct y_s_e_dist : gtl_yes {};
0626
0627 template <typename Segment, typename Point>
0628 typename enable_if<
0629 typename gtl_and_3<
0630 y_s_e_dist,
0631 typename is_segment_concept<
0632 typename geometry_concept<Segment>::type
0633 >::type,
0634 typename is_point_concept<
0635 typename geometry_concept<Point>::type
0636 >::type
0637 >::type,
0638 typename segment_distance_type<Segment>::type>::type
0639 euclidean_distance(const Segment& segment, const Point& point) {
0640 typedef typename segment_distance_type<Segment>::type Unit;
0641 Unit x1 = x(low(segment));
0642 Unit y1 = y(low(segment));
0643 Unit x2 = x(high(segment));
0644 Unit y2 = y(high(segment));
0645 Unit X = x(point);
0646 Unit Y = y(point);
0647 Unit A = X - x1;
0648 Unit B = Y - y1;
0649 Unit C = x2 - x1;
0650 Unit D = y2 - y1;
0651 Unit param = (A * C + B * D);
0652 Unit length_sq = C * C + D * D;
0653 if (param > length_sq) {
0654 return euclidean_distance(high(segment), point);
0655 } else if (param < 0.0) {
0656 return euclidean_distance(low(segment), point);
0657 }
0658 if (length_sq == 0.0)
0659 return 0.0;
0660 Unit denom = std::sqrt(length_sq);
0661 Unit result = (A * D - C * B) / denom;
0662 return (result < 0.0) ? -result : result;
0663 }
0664
0665 struct y_s_e_dist2 : gtl_yes {};
0666
0667 template <typename Segment1, typename Segment2>
0668 typename enable_if<
0669 typename gtl_and_3<
0670 y_s_e_dist2,
0671 typename is_segment_concept<
0672 typename geometry_concept<Segment1>::type
0673 >::type,
0674 typename is_segment_concept<
0675 typename geometry_concept<Segment2>::type
0676 >::type
0677 >::type,
0678 typename segment_distance_type<Segment1>::type>::type
0679 euclidean_distance(const Segment1& segment1, const Segment2& segment2) {
0680 if (intersects(segment1, segment2))
0681 return 0.0;
0682 typename segment_distance_type<Segment1>::type
0683 result1 = euclidean_distance(segment1, low(segment2)),
0684 result2 = euclidean_distance(segment1, high(segment2)),
0685 result3 = euclidean_distance(segment2, low(segment1)),
0686 result4 = euclidean_distance(segment2, high(segment1));
0687 if (result2 < result1)
0688 result1 = result2;
0689 if (result4 < result3)
0690 result3 = result4;
0691 return (result1 < result3) ? result1 : result3;
0692 }
0693 }
0694 }
0695
0696 #endif