分类 算法与数学基础 下的文章

计算两个凸多边形的交集可以用OpenCV、Boost、GEOS三个开源库实现: 1: OpenCV cv::intersectConvexConvex(a, b, intersectionPolygon, true)); true表示支持嵌套,即完全包含 2: Boost boost::geometry::intersection(A_polygon, B_polygon, output)) Boost的这个函数不支持嵌套,即一个凸多边形完全被另一个凸多边形包含,返回的交集面积为0.0. 3: GEOS(开源计算几何库) GEOSIntersection(pA, pB); // C_API ############################################################# \#include \#include \#include \#include \#include \#include \#include typedef boost::geometry::model::polygon > polygon; double Boost_Intersection_Of_Convex_Polygon(const std::vector &A, const std::vector &B,\ std::vector &intersectionPolygon) { /* polygon green, blue; boost::geometry::read_wkt( "POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3)" "(4.0 2.0, 4.2 1.4, 4.8 1.9, 4.4 2.2, 4.0 2.0))", green); boost::geometry::read_wkt( "POLYGON((4.0 -0.5 , 3.5 1.0 , 2.0 1.5 , 3.5 2.0 , 4.0 3.5 , 4.5 2.0 , 6.0 1.5 , 4.5 1.0 , 4.0 -0.5))", blue); std::deque output; */ if(A.size()<3 || B.size()<3) return 0.0; double area = 0.0; polygon A_polygon, B_polygon; for(const auto &pt:A){ boost::geometry::model::d2::point_xy point(pt.x, pt.y); boost::geometry::append(A_polygon, point); } for(const auto &pt:B){ boost::geometry::model::d2::point_xy point(pt.x, pt.y); boost::geometry::append(B_polygon, point); } std::deque output; if(!boost::geometry::intersection(A_polygon, B_polygon, output)){ //printf("Warning: boost::geometry::intersection was failed!\n"); return 0.0; // there no intersection. } double max_area = 0.0; polygon max_polggon; BOOST_FOREACH(polygon const& p, output){ area = boost::geometry::area(p); if(area>max_area){ max_area = area; max_polggon = p; } } intersectionPolygon.clear(); for(const auto &pt: max_polggon.outer()){ intersectionPolygon.push_back(cv::Point2f(static_cast(pt.x()), static_cast(pt.y()))); } printf("Boost A area:%f, B area:%f, intersection area:%f\n", boost::geometry::area(A_polygon), boost::geometry::area(B_polygon), max_area); bool is_overlap = boost::geometry::overlaps(A_polygon, B_polygon); printf("Boost overlap:%s\n", is_overlap?"Yes":"No"); boost::geometry::model::d2::point_xy pt; boost::geometry::centroid(A_polygon, pt); bool is_within = boost::geometry::within(B_polygon, A_polygon); printf("Boost %f,%f within A:%s\n", pt.x(), pt.y(), is_within?"Yes":"No"); boost::geometry::centroid(B_polygon, pt); is_within = boost::geometry::within(A_polygon, B_polygon); printf("Boost %f,%f within B:%s\n", pt.x(), pt.y(), is_within?"Yes":"No"); bool is_inside = boost::geometry::covered_by(A_polygon, B_polygon); std::cout<<"???:"< /* for printf */ \#include /* for va_list */ \#include \#include \#include \#include static void geos_msg_handler(const char* fmt, ...) { va_list ap; va_start(ap, fmt); vprintf (fmt, ap); va_end(ap); } double Geos_Intersection_Of_Convex_Polygon(const std::vector &A, const std::vector &B,\ std::vector &intersectionPolygon) { if(A.size()<3 || B.size()<3) return 0.0; initGEOS(geos_msg_handler, geos_msg_handler); std::vector Abuf, Bbuf; Abuf.assign(A.begin(), A.end()); Bbuf.assign(B.begin(), B.end()); //for close, the last point must same with the first point for GEOS lib. Abuf.push_back(A[0]); Bbuf.push_back(B[0]); double area = 0.0; GEOSCoordSequence* s1 = GEOSCoordSeq_copyFromBuffer((double *)Abuf.data(), Abuf.size(), 0, 0); GEOSCoordSequence* s2 = GEOSCoordSeq_copyFromBuffer((double *)Bbuf.data(), Bbuf.size(), 0, 0); if(nullptr==s1 || nullptr==s2) return 0.0; GEOSGeometry *p1 = GEOSGeom_createLinearRing(s1); GEOSGeometry *p2 = GEOSGeom_createLinearRing(s2); if(nullptr==p1 || nullptr==p2) return 0.0; GEOSGeometry *pA = GEOSGeom_createPolygon(p1, nullptr, 0); GEOSGeometry *pB = GEOSGeom_createPolygon(p2, nullptr, 0); if(nullptr==pA || nullptr==pB) return 0.0; double area_1 = 0.0, area_2 = 0.0; GEOSArea(pA, &area_1); GEOSArea(pB, &area_2); printf("PA area:%f, PB area:%f\n", area_1, area_2); GEOSGeometry *poverlay = GEOSIntersection(pA, pB); if(nullptr==poverlay){ std::cout<<"Err: GEOSIntersection return null!"< \#include \#include double OpenCV_Intersection_Of_Convex_Polygon(const std::vector &A, const std::vector &B,\ std::vector &intersectionPolygon) { if(A.size()<3 || B.size()<3) return 0.0; intersectionPolygon.clear(); std::vector a; std::vector b; a.resize(A.size()); b.resize(B.size()); for(int j=0; j(A[j].x), static_cast(A[j].y)); } for(int j=0; j(B[j].x), static_cast(B[j].y)); } for(const auto &pt:b){ std::cout<(cv::intersectConvexConvex(a, b, intersectionPolygon, true)); // opencv don't support double type. } ![intersection.png][1] [1]: /usr/uploads/2024/01/1445291094.png

cmake_minimum_required(VERSION 2.8 FATAL_ERROR) project(PCL_demo) find_package(Eigen3 3.3.4 REQUIRED) find_package(Boost REQUIRED) message(STATUS "boost:" ${Boost_INCLUDE_DIRS}) include_directories( ${EIGEN3_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ) add_executable(demo main.cpp) =============================================== \#include \#include \#include \#include \#include \#include \#include int main() { typedef boost::geometry::model::polygon > polygon; polygon green, blue; boost::geometry::read_wkt( "POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3)" "(4.0 2.0, 4.2 1.4, 4.8 1.9, 4.4 2.2, 4.0 2.0))", green); boost::geometry::read_wkt( "POLYGON((4.0 -0.5 , 3.5 1.0 , 2.0 1.5 , 3.5 2.0 , 4.0 3.5 , 4.5 2.0 , 6.0 1.5 , 4.5 1.0 , 4.0 -0.5))", blue); std::deque output; boost::geometry::intersection(green, blue, output); int i = 0; std::cout << "green && blue:" << std::endl; BOOST_FOREACH(polygon const& p, output) { std::cout << i++ << ": " << boost::geometry::area(p) << std::endl; } return 0; } ![Screenshot at 2024-01-10 17-18-17.png][1] [1]: /usr/uploads/2024/01/3565049934.png

1、背景

 同样一个旋转矩阵R,分别用Matlab与Eigen中的函数实现旋转矩阵到四元数,发现其结果有差异(本质是相同的):

     R:0 -0.277762 0.96065-1 0 00 -0.96065 -0.2777622、

Matlab的结果:

     rotm2quat(R)或 quat = quaternion(R', "rotmat", "frame")

  或 quat = quaternion(R, "rotmat", "point") 结果为: 0.4249,-0.5652,0.5652,-0.42493、


Eigen的结果:

    Eigen::Quaterniond Q(R) 结果为: -0.424923, 0.565191, -0.565191, 0.424923


结论:

         Eigen与Matlab的结果,整体差了一个负号,而一个四元数与其乘以一个负号,转成旋转矩阵是相同的。

    即四元数整体乘以-1,其表示的旋转是相同的。

    即: Q == -Q,即一个四元数乘以: -1  仍然等于自身!





1、Ceres Solver

开发语言: C++ 

官方地址: http://ceres-solver.org/ 

Ceres Solver 是一个开源c++库,用于建模和解决大型、复杂的优化问题。它可用于求解带边界约束的非线性最小二乘问题和一般的无约束优化问题。它是一个成熟的,功能丰富的,高性能的库。


2、NLopt

开发语言: C 

官方地址: https://nlopt.readthedocs.io/en/latest/#nlopt_1 

github: https://github.com/stevengj/nlopt/tree/master 

NLopt是一个用于非线性优化的免费/开源库,为许多不同的在线免费优化例程以及各种其他算法的原始实现提供了一个公共接口。



3、Ipopt

开发语言: C++ 

github: https://github.com/coin-or/Ipopt 

Ipopt (Interior Point OPTimizer,发音为eye-pea-Opt)是一个用于大规模非线性优化的软件包。



4、ALGLIB

 开发语言: C++

 官方地址: https://www.alglib.net/



5、g2o

开发语言: C++

github: https://github.com/RainerKuemmerle/g2o 

g20是一个开源的c++框架,用于优化基于图的非线性误差函数。g20被设计成可以很容易地扩展到广泛的问题,并且通常可以在几行代码中指定一个新问题。



6、GSL

开发语言: C/C++

官方地址: https://www.gnu.org/software/gsl/ 

GNU科学库(GSL)是一个面向C和c++程序员的数字库。它是GNU通用公共许可证下的自由软件。该库提供了广泛的数学例程,如随机数生成器,特殊函数和最小二乘拟合。



7、levmar

开发语言: C/C++ 

官方地址: http://users.ics.forth.gr/~lourakis/levmar/ 

evmar : 用C/C++实现的Levenberg-Marquardt 非线性最小二乘算法。 Levenberg-Marquardt (LM)算法是一种求函数的局部最小值的迭代技术,该函数表示为非线性函数的平方和。它已经成为非线性最小二乘问题的标准技术,可以被认为是最陡下降法和高斯-牛顿法的结合。当当前解与正确解相去甚远时,算法表现得像最陡下降法:缓慢,但保证收敛。当当前解接近正确解时,它成为高斯-牛顿方法。



8、OptimLib

开发语言: C/C++ 

官方地址: https://www.kthohr.com/optimlib.html

github: https://github.com/kthohr/optim

OptimLib是一个轻量级的c++库,用于非线性函数的数值优化方法。