#include <boost/assign.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/geometry.hpp> #include <boost/geometry/geometries/point_xy.hpp> #include <boost/geometry/geometries/linestring.hpp> #include <boost/geometry/geometries/box.hpp> #include <boost/geometry/geometries/ring.hpp> #include <boost/geometry/geometries/polygon.hpp> #include <boost/geometry/algorithms/transform.hpp> #include <boost/geometry/strategies/transform/inverse_transformer.hpp> #include <boost/geometry/strategies/transform/matrix_transformers.hpp> namespace bg = boost::geometry; typedef bg::model::d2::point_xy<double> DPoint; typedef bg::model::segment<DPoint> DSegment; typedef bg::model::linestring<DPoint> DLineString; typedef bg::model::box<DPoint> DBox; typedef bg::model::ring<DPoint, false> DRing; typedef bg::model::polygon<DPoint, false> DPolygon; //对Geometry库一些函数进行了封装,更加方便使用,包括(平移,旋转,缩放,求点到直线的垂足,通过比例求段上的点等等) namespace GeometryExtend { DPoint operator +(const DPoint& pt1, const DPoint& pt2) { DPoint pt(pt1); bg::add_point(pt, pt2); return pt; } const DPoint& operator +=(DPoint& pt1, const DPoint& pt2) { bg::add_point(pt1, pt2); return pt1; } DPoint operator -(const DPoint& pt1, const DPoint& pt2) { DPoint pt(pt1); bg::subtract_point(pt, pt2); return pt; } const DPoint& operator -=(DPoint& pt1, const DPoint& pt2) { bg::subtract_point(pt1, pt2); return pt1; } ////////////////////////////////////////////////////////////////////////// // 平移变换 ////////////////////////////////////////////////////////////////////////// template<typename Geometry, typename CalculationType> struct translate_impl { static void apply(Geometry& geometry, const CalculationType& x, const CalculationType& y) { bg::strategy::transform::translate_transformer<CalculationType, 2, 2> t(x, y); bg::transform(geometry, geometry, t); } }; template<typename Geometry, typename CalculationType> struct translate_trais { static void apply(Geometry& geometry, const CalculationType& x, const CalculationType& y); }; #define TRANSLATE_TRAIS(Geometry) template<typename CalculationType> struct translate_trais<Geometry, CalculationType> { static void apply(Geometry& geometry, const CalculationType& x, const CalculationType& y) { translate_impl<Geometry, CalculationType>::apply(geometry, x, y); } }; TRANSLATE_TRAIS(DPoint) TRANSLATE_TRAIS(DSegment) TRANSLATE_TRAIS(DBox) TRANSLATE_TRAIS(DRing) TRANSLATE_TRAIS(DPolygon) template<typename Geometry, typename CalculationType> void translate(Geometry& geometry, const CalculationType& x, const CalculationType& y) { translate_trais<Geometry, CalculationType>::apply(geometry, x, y); } ////////////////////////////////////////////////////////////////////////// // 旋转变换 ////////////////////////////////////////////////////////////////////////// template<typename Geometry, typename DegreeOrRadian, typename CalculationType> struct rotate_impl { static void apply(Geometry& geometry, const CalculationType& angle) { bg::strategy::transform::rotate_transformer<DegreeOrRadian, CalculationType, 2, 2> t(angle); bg::transform(geometry, geometry, t); } }; template<typename Geometry, typename DegreeOrRadian, typename CalculationType> struct rotate_trais { static void apply(Geometry& geometry, const CalculationType& angle); }; #define ROTATE_TRAIS(Geometry, DegreeOrRadian) template<typename CalculationType> struct rotate_trais<Geometry, DegreeOrRadian, CalculationType> { static void apply(Geometry& geometry, const CalculationType& angle) { rotate_impl<Geometry, DegreeOrRadian, CalculationType>::apply(geometry, angle); } }; ROTATE_TRAIS(DPoint, bg::degree) ROTATE_TRAIS(DPoint, bg::radian) ROTATE_TRAIS(DSegment, bg::degree) ROTATE_TRAIS(DSegment, bg::radian) ROTATE_TRAIS(DBox, bg::degree) ROTATE_TRAIS(DBox, bg::radian) ROTATE_TRAIS(DRing, bg::degree) ROTATE_TRAIS(DRing, bg::radian) ROTATE_TRAIS(DPolygon, bg::degree) ROTATE_TRAIS(DPolygon, bg::radian) template<typename Geometry, typename DegreeOrRadian, typename CalculationType> void rotate(Geometry& geometry, const DegreeOrRadian&, const CalculationType& angle) { rotate_trais<Geometry, DegreeOrRadian, CalculationType>::apply(geometry, angle); } template<typename Geometry, typename Point, typename DegreeOrRadian, typename CalculationType> void point_rotate(Geometry& geometry, const Point& point, const DegreeOrRadian& type, const CalculationType& angle) { Point pt(0, 0); bg::subtract_point(pt, point); translate(geometry, bg::get<0>(pt), bg::get<1>(pt)); rotate(geometry, type, angle); translate(geometry, bg::get<0>(point), bg::get<1>(point)); } ////////////////////////////////////////////////////////////////////////// // 比例变形 ////////////////////////////////////////////////////////////////////////// template<typename Geometry, typename CalculationType> struct scale_impl { static void apply(Geometry& geometry, const CalculationType& scale_x, const CalculationType& scale_y) { bg::strategy::transform::scale_transformer<CalculationType, 2, 2> t(scale_x, scale_y); bg::transform(geometry, geometry, t); } }; template<typename Geometry, typename CalculationType> struct scale_trais { static void apply(Geometry& geometry, const CalculationType& scale_x, const CalculationType& scale_y); }; #define SCALE_TRAIS(Geometry) template<typename CalculationType> struct scale_trais<Geometry, CalculationType> { static void apply(Geometry& geometry, const CalculationType& scale_x, const CalculationType& scale_y) { scale_impl<Geometry, CalculationType>::apply(geometry, scale_x, scale_y); } }; SCALE_TRAIS(DPoint) SCALE_TRAIS(DSegment) SCALE_TRAIS(DBox) SCALE_TRAIS(DRing) SCALE_TRAIS(DPolygon) template<typename Geometry, typename CalculationType> void scale(Geometry& geometry, const CalculationType& scale_x, const CalculationType& scale_y) { scale_trais<Geometry, CalculationType>::apply(geometry, scale_x, scale_y); } ////////////////////////////////////////////////////////////////////////// // 函数功能: // 扩充box ////////////////////////////////////////////////////////////////////////// template<typename Geometry, typename CalculateType> void InflateBox(Geometry& geometry, CalculateType const& cx, CalculateType const& cy) { typedef typename bg::point_type<Geometry>::type point_type; point_type& ptMin = geometry.min_corner(); point_type& ptMax = geometry.max_corner(); ptMin.x(ptMin.x() - cx); ptMin.y(ptMin.y() - cy); ptMax.x(ptMax.x() + cx); ptMax.y(ptMax.y() + cy); } ////////////////////////////////////////////////////////////////////////// // 函数功能: // 求点到线段的垂足; // 返回值: // true,垂足在线段上; // false,垂足在线段外; ////////////////////////////////////////////////////////////////////////// template<typename Point, typename Segment> bool point_to_segment_org(Point const& point, Segment const& segment, Point& ptOut) { bool bInSegment = true; try { typedef typename bg::point_type<Segment>::type point_type; point_type p[2] = {segment.first, segment.second}; if (boost::geometry::equals(point, p[0]) || boost::geometry::equals(point, p[1])) { boost::geometry::assign_point(ptOut, point); bInSegment = true; throw bInSegment; } point_type v(p[1]), w(point); boost::geometry::subtract_point(v, p[0]); boost::geometry::subtract_point(w, p[0]); typedef typename bg::select_calculation_type<Point, Segment, void>::type calculation_type; calculation_type const zero = calculation_type(); calculation_type const c1 = boost::geometry::dot_product(w, v); if (c1 < zero) { bInSegment = false; } double const c2 = boost::geometry::dot_product(v, v); if (c2 < c1) { bInSegment = false; } calculation_type const b = c1 / c2; DPoint projected(p[0]); boost::geometry::multiply_value(v, b); boost::geometry::add_point(projected, v); boost::geometry::assign_point(ptOut, projected); } catch (bool) { } return bInSegment; } ////////////////////////////////////////////////////////////////////////// // 函数功能: // 通过比例求段上的点; ////////////////////////////////////////////////////////////////////////// template<typename Segment, typename Point> void get_segment_on_point_by_scale(Segment const& segment, double const& dScale, Point& ptOut) { typedef typename bg::point_type<Segment>::type point_type; point_type p[2] = {segment.first, segment.second}; point_type v(p[1]); point_type ptDest(p[0]); boost::geometry::subtract_point(v, p[0]); boost::geometry::multiply_value(v, dScale); boost::geometry::add_point(ptDest, v); boost::geometry::assign_point(ptOut, ptDest); } ////////////////////////////////////////////////////////////////////////// // 函数功能: // 通过长度求段上的点; ////////////////////////////////////////////////////////////////////////// template<typename Segment, typename Point> void get_segment_on_point_by_length(Segment const& segment, double const& dLength, Point& ptOut) { typedef typename bg::point_type<Segment>::type point_type; point_type p[2] = {segment.first, segment.second}; double dTotalLength = boost::geometry::distance(p[0], p[1]); double dScale = dLength / dTotalLength; get_segment_on_point_by_scale(segment, dScale, ptOut); } } int main() { DBox box1(DPoint(100, 100), DPoint(300, 200)); GeometryExtend::InflateBox(box1, 20, 10); DSegment sg1(DPoint(100, 100), DPoint(300, 300)); DPoint pt1(300, 100); DPoint pt2(100, 0); DPoint ptOut; bool bOnSegment; bOnSegment = GeometryExtend::point_to_segment_org(pt1, sg1, ptOut); bOnSegment = GeometryExtend::point_to_segment_org(pt2, sg1, ptOut); GeometryExtend::get_segment_on_point_by_scale(sg1, 0.5, ptOut); GeometryExtend::get_segment_on_point_by_length(sg1, 0, ptOut); DPoint pt4; DSegment sg4; //平移变换 bg::assign_point(pt4, pt1); GeometryExtend::translate(pt4, 10, 20); bg::assign(sg4, sg1); GeometryExtend::translate(sg4, 10, 20); //旋转变形 bg::assign(pt4, pt1); GeometryExtend::rotate(pt4, bg::degree(), 45.0); bg::assign(sg4, sg1); GeometryExtend::rotate(sg4, bg::degree(), 45.0); //比例变换 bg::assign(pt4, pt1); GeometryExtend::scale(pt4, 0.5, 0.2); bg::assign(sg4, sg1); GeometryExtend::scale(sg4, 0.5, 0.2); return 0; }