• boost库之geometry<二>


    #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;
    }
    
  • 相关阅读:
    JavaScript-4.5 事件大全,事件监听---ShinePans
    SparseArray具体解释,我说SparseArray,你说要!
    Spark Core源代码分析: RDD基础
    我的 Android 开发实战经验总结
    物联网的一种參考架构
    【LeetCode】 Rotate List 循环链表
    放苹果(整数划分变形题 水)poj1664
    ps白平衡
    jfinal对象封装Record原理
    ps通道混合器
  • 原文地址:https://www.cnblogs.com/dongc/p/5225125.html
Copyright © 2020-2023  润新知