Boost库-功能介绍-Geometry-图形开发库-计算几何-常用功能封装-GraphicalDebugging(二)

  有了上一篇博文打下的基础,读者应该对分析查看几何图形有了初步了解,本着实用的原则,这篇文章,主要介绍Geometry的常用计算。它提供了点线面相交,相离的判断,以及多边形的布尔运算,在几何分析中非常有用,如果读者对深入学习Geometry感兴趣,需要深入学习泛型编程,作者在学习过程中也是感到深深的吃力,特别是缓冲区的代码,SDK提供的算法有时计算不出结果,详情查看注释,代码如下:

//ANormGeoLib.h--计算文件
#pragma once
#include <boost/geometry.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/geometries/adapted/boost_tuple.hpp>
#include <boost/assign.hpp>
#include <vector>

namespace bg = boost::geometry;
typedef bg::model::d2::point_xy<double, boost::geometry::cs::cartesian> 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, true> DRing; //环
typedef bg::model::polygon<DPoint, false> DPolygon; //多边形
typedef bg::model::multi_polygon<DPolygon> DMultiPolygon;//多个多边形
typedef bg::model::multi_point<DPoint> DMultiPoint;//多点

#define A_PI 3.141592653589793238462643383279502884197
namespace ANormGeoLib
{
	// 二维空间点到直线的垂足
	struct _Point
	{
		double x, y;

		_Point(double x, double y) :x(x), y(y)
		{

		}
		_Point() :x(0), y(0)
		{

		}
	};

	//获取垂足
	inline _Point GetFootOfPerpendicular(
		const _Point &pt,     // 直线外一点
		const _Point &begin,  // 直线开始点
		const _Point &end)    // 直线结束点
	{
		_Point retVal;
		double dx = begin.x - end.x;
		double dy = begin.y - end.y;
		if (abs(dx) < 0.00000001 && abs(dy) < 0.00000001)
		{
			retVal = begin;
			return retVal;
		}
		double u = (pt.x - begin.x)*(begin.x - end.x) +
			(pt.y - begin.y)*(begin.y - end.y);
		u = u / ((dx*dx) + (dy*dy));
		retVal.x = begin.x + u*dx;
		retVal.y = begin.y + u*dy;
		return retVal;
	}

	//角度转弧度
	inline double Degree2Radius(double d)
	{
		double rlt = d*A_PI / 180;
		return rlt;
	}

	//弧度转角度
	inline double Radius2Degree(double r)
	{
		double rlt = r * 180 / A_PI;
		return rlt;
	}

	//1.两点之间的距离
	template<typename T1,typename T2,typename T3,typename T4,typename T5>
	inline T1 Distance(T2 x1, T3 y1, T4 x2, T5 y2)
	{
		double dx1 = x1, dx2 = x2, dy1 = y1, dy2 = y2;
		double dr = ::sqrt((dx1 - dx2)*(dx1 - dx2) + (dy1 - dy2)*(dy1 - dy2));
		T1 d = static_cast<T1>(dr);
		return d;
	}

	//2.点到线段的垂足并返回到垂足的距离
	template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
	inline T1 Point2Segment(T2 px1, T3 py1, T4 lx1, T5 ly1, T6 lx2, T7 ly2, T8& poutx, T9& pouty)
	{
		_Point pt = { (double)px1, (double)py1 };
		_Point begin = { (double)lx1, (double)ly1 };
		_Point end = { (double)lx2, (double)ly2 };
		_Point rlt = GetFootOfPerpendicular(pt, begin, end);
		poutx = static_cast<T8>(rlt.x);
		pouty = static_cast<T9>(rlt.y);

		return Distance<T1>(px1, py1, poutx, pouty);		
	}

	//3.点在正常笛卡尔坐标系空间中的逆时针方向角
	template<typename T1, typename T2, typename T3>
	inline T1 DirectAngleByPoint(T2 x, T3 y)
	{
		double angle=0;
		_Point pt = { (double)x, (double)y };
		if (pt.x==0)
		{
			if (pt.y>0)
			{
				angle = 90;
			}
			else if(pt.y<0)
			{
				angle = 270;
			}
			else
			{
				angle = 0;
			}
		}
		else
		{
			angle = std::atan2(pt.y, pt.x);
			angle = Radius2Degree(angle);
			if (angle < 0)
			{
				angle = angle + 360;
			}
		}

		T1 rlt = static_cast<T1>(angle);
		return rlt;		
	}

	//4.计算三角形的面积
	template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
	inline T1 AreaBy3Points(T2 px1, T3 py1, T4 px2, T5 py2, T6 px3, T7 py3)
	{
		_Point pt = { (double)px1, (double)py1 };
		_Point begin = { (double)px2, (double)py2 };
		_Point end = { (double)px3, (double)py3 };
		_Point foot = GetFootOfPerpendicular(pt, begin, end);

		double h = Distance<double>(px1, py1, foot.x, foot.y);
		double l = Distance<double>(px2, py2, px3, py3);
		double a = h*l / 2;
		T1 ar = static_cast<T1>(a);
		return ar;
	}

	//5.多边形的缓冲区buffer,缓冲区的计算不是都能成功
	template<typename T1>
	inline bool PolygonBufferRegion(const std::vector<T1>& pointListSrc, std::vector<T1>& pointListDst, double dis, int ppc)
	{
		//申明策略
		const double buffer_distance = dis;
		const int points_per_circle = ppc;
		boost::geometry::strategy::buffer::distance_symmetric<double> distance_strategy(buffer_distance);
		boost::geometry::strategy::buffer::join_round join_strategy(points_per_circle);
		boost::geometry::strategy::buffer::end_round end_strategy(points_per_circle);
		boost::geometry::strategy::buffer::point_circle circle_strategy(points_per_circle);
		boost::geometry::strategy::buffer::side_straight side_strategy;

		//转为多边形		
		std::vector<DPoint> ptList;
		int pointListSrcSize = pointListSrc.size();
		for (int i = 0; i < pointListSrcSize;i++)
		{
			DPoint pt(pointListSrc[i].x, pointListSrc[i].y);
			ptList.push_back(pt);
		}
		DPolygon polySrc;
		bg::assign_points(polySrc, ptList);
		bg::correct(polySrc);

		//计算缓存区
		DMultiPolygon result;
		if (boost::geometry::is_valid(polySrc))
		{
			//创建缓存
			DMultiPolygon result2;
			boost::geometry::buffer(polySrc, result,
				distance_strategy, side_strategy,
				join_strategy, end_strategy, circle_strategy);
		}
		
		//转换结果
		if (result.empty())
		{
			return false;
		}
		else
		{
			pointListDst.clear();
			BOOST_AUTO(poly, result[0].outer());
			int ptSize = poly.size();
			for (int i = 0; i < ptSize;i++)
			{
				T1 pt;
				pt.x = poly[i].x();
				pt.y = poly[i].y();
				pointListDst.push_back(pt);
			}
			return true;			
		}
	}
};

  调用范例代码如下所示:

#include "ANormGeoLib.h"
int main()
{
	//两点间距离
	double d1 = ANormGeoLib::Distance<double>(0, 0, 10, 10);

	//点到线段的垂足和距离
	double xout, yout;
	double d2 = ANormGeoLib::Point2Segment<double>(10, 10, 20, 20, 20, 0, xout, yout);

	//点的角度
	double d3 = ANormGeoLib::DirectAngleByPoint<double>(0, -90);

	//三角形面积
	double d4 = ANormGeoLib::AreaBy3Points<double>(0, 10, -5, 0, 5, 0);

	//缓冲区
	std::vector<ANormGeoLib::_Point> srcPts, dstPts;
	srcPts.push_back(ANormGeoLib::_Point(0.0, 0));
	srcPts.push_back(ANormGeoLib::_Point(15.0, 0));
	srcPts.push_back(ANormGeoLib::_Point(16, 18));
	srcPts.push_back(ANormGeoLib::_Point(0, 19));
	srcPts.push_back(ANormGeoLib::_Point(0.0, 0));
	ANormGeoLib::PolygonBufferRegion<ANormGeoLib::_Point>(srcPts, dstPts, 5, 36);
	return 0;
}

  这是作者在研究几何计算项目时经常需要解决的问题,供读者分享。
  Geometry官方网址:https://www.boost.org/doc/libs/1_73_0/libs/geometry/doc/html/geometry/reference.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值