|
|
00001 // Boost.Geometry (aka GGL, Generic Geometry Library) 00002 // 00003 // Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands. 00004 // Copyright Bruno Lalande 2008, 2009 00005 // Use, modification and distribution is subject to the Boost Software License, 00006 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 00007 // http://www.boost.org/LICENSE_1_0.txt) 00008 00009 #ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP 00010 #define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP 00011 00012 #include <algorithm> 00013 00014 #include <boost/concept_check.hpp> 00015 00016 #include <boost/geometry/core/access.hpp> 00017 #include <boost/geometry/strategies/side_info.hpp> 00018 #include <boost/geometry/util/select_calculation_type.hpp> 00019 #include <boost/geometry/util/select_most_precise.hpp> 00020 00021 00022 namespace boost { namespace geometry 00023 { 00024 00025 namespace policies { namespace relate { 00026 00027 00028 template <typename S1, typename S2, typename ReturnType, typename CalculationType = void> 00029 struct segments_intersection_points 00030 { 00031 typedef ReturnType return_type; 00032 typedef S1 segment_type1; 00033 typedef S2 segment_type2; 00034 typedef typename select_calculation_type 00035 < 00036 S1, S2, CalculationType 00037 >::type coordinate_type; 00038 00039 // Get the same type, but at least a double 00040 typedef typename select_most_precise<coordinate_type, double>::type rtype; 00041 00042 static inline return_type segments_intersect(side_info const&, 00043 coordinate_type const& dx1, coordinate_type const& dy1, 00044 coordinate_type const& dx2, coordinate_type const& dy2, 00045 S1 const& s1, S2 const& s2) 00046 { 00047 return_type result; 00048 typedef typename geometry::coordinate_type 00049 < 00050 typename return_type::point_type 00051 >::type coordinate_type; 00052 00053 // Get the same type, but at least a double (also used for divisions 00054 typedef typename select_most_precise 00055 < 00056 coordinate_type, double 00057 >::type promoted_type; 00058 00059 promoted_type const s1x = get<0, 0>(s1); 00060 promoted_type const s1y = get<0, 1>(s1); 00061 00062 // Calculate other determinants - Cramers rule 00063 promoted_type const wx = get<0, 0>(s1) - get<0, 0>(s2); 00064 promoted_type const wy = get<0, 1>(s1) - get<0, 1>(s2); 00065 promoted_type const d = (dy2 * dx1) - (dx2 * dy1); 00066 promoted_type const da = (promoted_type(dx2) * wy) - (promoted_type(dy2) * wx); 00067 00068 // r: ratio 0-1 where intersection divides A/B 00069 promoted_type const r = da / d; 00070 00071 result.count = 1; 00072 set<0>(result.intersections[0], 00073 boost::numeric_cast<coordinate_type>(s1x + r * promoted_type(dx1))); 00074 set<1>(result.intersections[0], 00075 boost::numeric_cast<coordinate_type>(s1y + r * promoted_type(dy1))); 00076 00077 return result; 00078 } 00079 00080 static inline return_type collinear_touch(coordinate_type const& x, 00081 coordinate_type const& y, int, int) 00082 { 00083 return_type result; 00084 result.count = 1; 00085 set<0>(result.intersections[0], x); 00086 set<1>(result.intersections[0], y); 00087 return result; 00088 } 00089 00090 template <typename S> 00091 static inline return_type collinear_inside(S const& s, int index1 = 0, int index2 = 1) 00092 { 00093 return_type result; 00094 result.count = 2; 00095 set<0>(result.intersections[index1], get<0, 0>(s)); 00096 set<1>(result.intersections[index1], get<0, 1>(s)); 00097 set<0>(result.intersections[index2], get<1, 0>(s)); 00098 set<1>(result.intersections[index2], get<1, 1>(s)); 00099 return result; 00100 } 00101 00102 template <typename S> 00103 static inline return_type collinear_interior_boundary_intersect(S const& s, bool a_in_b, 00104 int, int, bool opposite) 00105 { 00106 int index1 = opposite && ! a_in_b ? 1 : 0; 00107 return collinear_inside(s, index1, 1 - index1); 00108 } 00109 00110 static inline return_type collinear_a_in_b(S1 const& s, bool opposite) 00111 { 00112 return collinear_inside(s); 00113 } 00114 static inline return_type collinear_b_in_a(S2 const& s, bool opposite) 00115 { 00116 int index1 = opposite ? 1 : 0; 00117 return collinear_inside(s, index1, 1 - index1); 00118 } 00119 00120 static inline return_type collinear_overlaps( 00121 coordinate_type const& x1, coordinate_type const& y1, 00122 coordinate_type const& x2, coordinate_type const& y2, 00123 int, int, bool) 00124 { 00125 return_type result; 00126 result.count = 2; 00127 set<0>(result.intersections[0], x1); 00128 set<1>(result.intersections[0], y1); 00129 set<0>(result.intersections[1], x2); 00130 set<1>(result.intersections[1], y2); 00131 return result; 00132 } 00133 00134 static inline return_type segment_equal(S1 const& s, bool opposite) 00135 { 00136 return_type result; 00137 result.count = 2; 00138 // TODO: order of IP's 00139 set<0>(result.intersections[0], get<0, 0>(s)); 00140 set<1>(result.intersections[0], get<0, 1>(s)); 00141 set<0>(result.intersections[1], get<1, 0>(s)); 00142 set<1>(result.intersections[1], get<1, 1>(s)); 00143 return result; 00144 } 00145 00146 static inline return_type disjoint() 00147 { 00148 return return_type(); 00149 } 00150 static inline return_type error(std::string const& msg) 00151 { 00152 return return_type(); 00153 } 00154 00155 static inline return_type collinear_disjoint() 00156 { 00157 return return_type(); 00158 } 00159 static inline return_type parallel() 00160 { 00161 return return_type(); 00162 } 00163 static inline return_type degenerate(S1 const& s, bool) 00164 { 00165 return_type result; 00166 result.count = 1; 00167 set<0>(result.intersections[0], get<0, 0>(s)); 00168 set<1>(result.intersections[0], get<0, 1>(s)); 00169 return result; 00170 } 00171 }; 00172 00173 00174 }} // namespace policies::relate 00175 00176 }} // namespace boost::geometry 00177 00178 #endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
|
December 1, 2009 |
Copyright © 1995-2009 Barend Gehrels, Geodan, Amsterdam Copyright © 2008-2009 Bruno Lalande, Paris Copyright © 2009 Mateusz Loskot, Cadcorp, London |