C++模板特化实战:在使用开源库boost::geometry::index::rtree时,用特化来让其支持自己的数据类型

 用自己定义的数据结构作为rtree的key。


// rTree的key
struct OverlapKey
{
    using BDPoint = boost::geometry::model::point<double, 3, boost::geometry::cs::cartesian>; //双精度的点
    using MyRTree = boost::geometry::index::rtree<OverlapKey, boost::geometry::index::linear<16> >;

    BDPoint GetKey() { return key; }

    std::wstring id;

    //key
    BDPoint key;

    std::list<DgnHistory::FarElementID> mCurveLst;

    //         std::greater<double>>, std::less<int>> mData;
    /*--------------------------------------------------------------------------------------**//**
    * 将对方向相同的曲线(一般情况下是直线)进行分类,                                            
    *                                                            Created by Simon.Zou on 9/2021
    +---------------+---------------+---------------+---------------+---------------+-----------*/
    //std::set<DataPtr, Data::DataSort> mData; 
    void AddData(DgnHistory::FarElementID data)
    {
        mCurveLst.push_back(data);
    }

    OverlapKey()
    {
        boost::uuids::uuid a_uuid = boost::uuids::random_generator()(); // 这里是两个() ,因为这里是调用的 () 的运算符重载
        id = boost::uuids::to_wstring(a_uuid);

        key.set<0>(0);
        key.set<1>(0);
        key.set<2>(0);
        //ICurvePrimitivePtr = NULL;
    }

    OverlapKey(const OverlapKey& r)
    {
        *this = r;
    }

    OverlapKey(OverlapKey&& r)
    {
        this->id = r.id;
        this->key = r.key;
        mCurveLst = r.mCurveLst;

        r.id = L"";
        r.key.set<0>(0);
        r.key.set<1>(0);
        r.key.set<2>(0);
        r.mCurveLst.clear();
    }

    OverlapKey& operator=(const OverlapKey& r)
    {
        this->id = r.id;
        this->key = r.key;
        mCurveLst = r.mCurveLst;
        //this->ICurvePrimitivePtr = r.ICurvePrimitivePtr;
        return *this;
    }

    OverlapKey& operator=(OverlapKey&& r)
    {
        this->id = r.id;
        this->key = r.key;
        mCurveLst = r.mCurveLst;
        //this->ICurvePrimitivePtr = r.ICurvePrimitivePtr;

        r.id = L"";
        r.key.set<0>(0);
        r.key.set<1>(0);
        r.key.set<2>(0);
        r.mCurveLst.clear();

        return *this;
    }

    //rTree.remove(...)函数会用到
    bool operator == (const OverlapKey& o) const
    {
        bool b1 = fabs(key.get<0>() - o.key.get<0>()) < 0.001;
        bool b2 = fabs(key.get<1>() - o.key.get<1>()) < 0.001;
        bool b3 = fabs(key.get<2>() - o.key.get<2>()) < 0.001;
        if (b1 && b2 && b3)
            return true;

        _SaveLog_Info_return_false("return false")
    }
};

/*--------------------------------------------------------------------------------------**//**
*  为了能把自己的数据结构OverlapKey用到boost的rtree里,创建此特化                                           
*                                                            Created by Simon.Zou on 9/2021
+---------------+---------------+---------------+---------------+---------------+-----------*/
template <>
struct boost::geometry::index::indexable<OverlapKey>
{
    typedef OverlapKey::BDPoint result_type; //这个不能缺少
    const OverlapKey::BDPoint& operator()(const OverlapKey& c) const
    {
        return c.key;
    }
};
/*--------------------------------------------------------------------------------------+
|   HchxAlgorithm.cpp
|
+--------------------------------------------------------------------------------------*/
#include "HchxUnitTestPch.h"

#include "gtest\gtest.h"

using namespace std;
using namespace boost;

USING_NAMESPACE_BENTLEY_ECOBJECT;

#include <cmath>
#include <vector>
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/io/dsv/write.hpp>
#include <boost/foreach.hpp>


bool boost_test1()
{
    namespace bg = boost::geometry;
    namespace bgi = boost::geometry::index;
    typedef bg::model::point<double, 2, bg::cs::cartesian> DPoint;
    typedef bg::model::box<DPoint> DBox;
    typedef bg::model::polygon<DPoint, false, false> DPolygon; // ccw, open polygon
    typedef std::pair<DBox, unsigned> DValue;

	std::vector<DPolygon> polygons;

	//构建多边形
	for (unsigned i = 0; i < 10; ++i)
	{
		//创建多边形
		DPolygon p;
		for (float a = 0; a < 6.28316f; a += 1.04720f)
		{
			float x = i + int(10 * ::cos(a))*0.1f;
			float y = i + int(10 * ::sin(a))*0.1f;
			p.outer().push_back(DPoint(x, y));
		}

		//插入
		polygons.push_back(p);
	}

	//打印多边形值
	std::cout << "generated polygons:" << std::endl;
	BOOST_FOREACH(DPolygon const& p, polygons)
		std::cout << bg::wkt<DPolygon>(p) << std::endl;

	//创建R树
	bgi::rtree< DValue, bgi::rstar<16, 4> > rtree; //最大最小

	//计算多边形包围矩形并插入R树
	for (unsigned i = 0; i < polygons.size(); ++i)
	{
		//计算多边形包围矩形
		DBox b = bg::return_envelope<DBox>(polygons[i]);
		//插入R树
		rtree.insert(std::make_pair(b, i));
	}

	//按矩形范围查找
	DBox query_box(DPoint(0, 0), DPoint(5, 5));
	std::vector<DValue> result_s;
	rtree.query(bgi::intersects(query_box), std::back_inserter(result_s));

	//5个最近点
	std::vector<DValue> result_n;
	rtree.query(bgi::nearest(DPoint(0, 0), 5), std::back_inserter(result_n));

	// note: in Boost.Geometry the WKT representation of a box is polygon
	// note: the values store the bounding boxes of polygons
	// the polygons aren't used for querying but are printed

	// display results
	std::cout << "spatial query box:" << std::endl;
	std::cout << bg::wkt<DBox>(query_box) << std::endl;
	std::cout << "spatial query result:" << std::endl;
	BOOST_FOREACH(DValue const& v, result_s)
		std::cout << bg::wkt<DPolygon>(polygons[v.second]) << std::endl;

	std::cout << "knn query point:" << std::endl;
	std::cout << bg::wkt<DPoint>(DPoint(0, 0)) << std::endl;
	std::cout << "knn query result:" << std::endl;
	BOOST_FOREACH(DValue const& v, result_n)
		std::cout << bg::wkt<DPolygon>(polygons[v.second]) << std::endl;

	return true;
}

void boost_test2()
{
    namespace bg = boost::geometry;
    namespace bgi = boost::geometry::index;
    typedef bg::model::d2::point_xy<double, boost::geometry::cs::cartesian> DPoint; //双精度的点
    typedef bg::model::polygon<DPoint, false, false> DPolygon; // ccw, open polygon
    typedef bg::model::box<DPoint> DBox; //矩形
    typedef std::pair<DBox, unsigned> Value;

	//创建R树 linear quadratic rstar三种算法
    bgi::rtree<Value, bgi::quadratic<16>> rtree;//采用quadratic algorithm,节点中元素个数最多16个
    //bgi::rtree<Value, bgi::rstar<32>> rtree;//采用quadratic algorithm,节点中元素个数最多16个
    //bgi::rtree<Value, bgi::linear<32>> rtree;//采用quadratic algorithm,节点中元素个数最多16个
    //bgi::rtree<std::pair<DBox, std::string>, bgi::rstar<16> > rtree;

	//填充元素
// 	for (unsigned i = 0; i < 10; ++i)
// 	{
// 		DBox b(DPoint(i + 0.0f, i + 0.0f), DPoint(i + 0.5f, i + 0.5f));
// 		rtree.insert(std::make_pair(b, i));//r树插入外包围矩形 i为索引
// 	}

    DBox b1(DPoint(0.0f, 0.0f), DPoint(1.0f, 1.0f));
    rtree.insert(std::make_pair(b1, 0));//r树插入外包围矩形 i为索引
    DBox b2(DPoint(-1.0f, -1.0f), DPoint(0.0f, 0.0f));
    rtree.insert(std::make_pair(b2, 1));//r树插入外包围矩形 i为索引
    DBox b3(DPoint(0.0f, 0.0f), DPoint(1.5f, 1.5f));
    rtree.insert(std::make_pair(b3, 2));//r树插入外包围矩形 i为索引

	//查询与矩形相交的矩形索引
	DBox query_box(DPoint(-0.1f, -0.1f), DPoint(1.2f, 1.2f));
	std::vector<Value> result_s;

    //https://www.boost.org/doc/libs/1_54_0/libs/geometry/doc/html/geometry/spatial_indexes/queries.html
    //查出与query_box相交的所有box。可以overlaps,也可以是包含关系。
    //rtree.query(bgi::intersects(query_box), std::back_inserter(result_s));

    //被query_box完全覆盖的所有box
    //rtree.query(bgi::covered_by(query_box), std::back_inserter(result_s));

    //查出所有包含query_box的box。注意是“包含”。如果仅仅是相交,是不会放到结果集中的。
    rtree.query(bgi::covers(query_box), std::back_inserter(result_s)); 

    //查出与query_box不相交的集合。这些集合和query_box没有任何重叠。
    //rtree.query(bgi::disjoint(query_box), std::back_inserter(result_s));

    //查出与query_box相交的集合。与intersects不同的是:如果query_box在box内部,那么这个box不会被记录到结果集。
    //rtree.query(bgi::overlaps(query_box), std::back_inserter(result_s));

    //查到被query_box完全包含的box。不包含那种相交的
    //rtree.query(bgi::within(query_box), std::back_inserter(result_s));
    //rtree.bgi::query(bgi::intersects(box), std::back_inserter(result));

    /*--------------------------------------------------------------------------------------**//**
    *  支持ring和polygon                                       Commented by Simon.Zou on 5/2021
    +---------------+---------------+---------------+---------------+---------------+-----------*/


	//查找5个离点最近的索引
	std::vector<Value> result_n;
	rtree.query(bgi::nearest(DPoint(0, 0), 5), std::back_inserter(result_n));

	//显示值
	std::cout << "spatial query box:" << std::endl;
	std::cout << bg::wkt<DBox>(query_box) << std::endl;
	std::cout << "spatial query result:" << std::endl;
	//BOOST_FOREACH(Value const& v, result_s)
	//	std::cout << bg::wkt<DBox>(v.first) << " - " << v.second << std::endl;

	std::cout << "knn query point:" << std::endl;
	std::cout << bg::wkt<DPoint>(DPoint(0, 0)) << std::endl;
	std::cout << "knn query result:" << std::endl;
	//BOOST_FOREACH(Value const& v, result_n)
	//	std::cout << bg::wkt<DBox>(v.first) << " - " << v.second << std::endl;
}

void boost_test3()
{
    using namespace boost::assign;
    typedef boost::geometry::model::d2::point_xy<double> point_xy;

    // Create points to represent a 5x5 closed polygon.
    std::vector<point_xy> points;
    points +=
        point_xy(0, 0),
        point_xy(0, 5),
        point_xy(5, 5),
        point_xy(5, 0),
        point_xy(0, 0)
        ;

    // Create a polygon object and assign the points to it.
    boost::geometry::model::polygon<point_xy> polygon;
    boost::geometry::assign_points(polygon, points);

    std::cout << "Polygon " << boost::geometry::dsv(polygon) <<
        " has an area of " << boost::geometry::area(polygon) << std::endl;
}

/*--------------------------------------------------------------------------------------**//**
*  用polygon来查询                                       Commented by Simon.Zou on 5/2021
+---------------+---------------+---------------+---------------+---------------+-----------*/
void boost_test4()
{
    namespace bg = boost::geometry;
    namespace bgi = boost::geometry::index;
    typedef bg::model::d2::point_xy<double, boost::geometry::cs::cartesian> DPoint; //双精度的点
    typedef bg::model::polygon<DPoint, false, false> DPolygon; // ccw, open polygon
    typedef bg::model::box<DPoint> DBox; //矩形
    typedef std::pair<DBox, unsigned> Value;

	//创建R树 linear quadratic rstar三种算法
    bgi::rtree<Value, bgi::quadratic<16>> rtree;//采用quadratic algorithm,节点中元素个数最多16个
    //bgi::rtree<Value, bgi::rstar<32>> rtree;//采用quadratic algorithm,节点中元素个数最多16个
    //bgi::rtree<Value, bgi::linear<32>> rtree;//采用quadratic algorithm,节点中元素个数最多16个
    //bgi::rtree<Value, bgi::rstar<16>> rtree;//采用quadratic algorithm,节点中元素个数最多16个
    //bgi::rtree<std::pair<DBox, std::string>, bgi::rstar<16> > rtree;

	//填充元素
// 	for (unsigned i = 0; i < 10; ++i)
// 	{
// 		DBox b(DPoint(i + 0.0f, i + 0.0f), DPoint(i + 0.5f, i + 0.5f));
// 		rtree.insert(std::make_pair(b, i));//r树插入外包围矩形 i为索引
// 	}

    DBox b1(DPoint(0.0f, 0.0f), DPoint(1.0f, 1.0f));
    rtree.insert(std::make_pair(b1, 0));//r树插入外包围矩形 i为索引
    DBox b2(DPoint(-1.0f, -1.0f), DPoint(0.0f, 0.0f));
    rtree.insert(std::make_pair(b2, 1));//r树插入外包围矩形 i为索引
    DBox b3(DPoint(0.0f, 0.0f), DPoint(1.5f, 1.5f));
    rtree.insert(std::make_pair(b3, 2));//r树插入外包围矩形 i为索引

	//查询与矩形相交的矩形索引
	DBox query_box(DPoint(-0.1f, -0.1f), DPoint(1.2f, 1.2f));
	std::vector<Value> result_s;

    /*--------------------------------------------------------------------------------------**//**
    *  支持ring和polygon                                       Commented by Simon.Zou on 5/2021
    +---------------+---------------+---------------+---------------+---------------+-----------*/
    using namespace boost::assign;
    typedef boost::geometry::model::d2::point_xy<double> point_xy;

    // Create points to represent a 5x5 closed polygon.
    std::vector<point_xy> points;
    points += point_xy(0.1, 0.1), 
        point_xy(0.1, 5),
        point_xy(2.5, 5),
        point_xy(5, 2.5),
        point_xy(5, 0.1),
        point_xy(0.1, 0.1);

    // Create a polygon object and assign the points to it.
    boost::geometry::model::polygon<point_xy> polygon;
    DPolygon p;
    boost::geometry::assign_points(p, points);
    rtree.query(bgi::intersects(p), std::back_inserter(result_s));


	//查找5个离点最近的索引
	std::vector<Value> result_n;
	rtree.query(bgi::nearest(DPoint(0, 0), 5), std::back_inserter(result_n));

	//显示值
	std::cout << "spatial query box:" << std::endl;
	std::cout << bg::wkt<DBox>(query_box) << std::endl;
	std::cout << "spatial query result:" << std::endl;
	//BOOST_FOREACH(Value const& v, result_s)
	//	std::cout << bg::wkt<DBox>(v.first) << " - " << v.second << std::endl;

	std::cout << "knn query point:" << std::endl;
	std::cout << bg::wkt<DPoint>(DPoint(0, 0)) << std::endl;
	std::cout << "knn query result:" << std::endl;
	//BOOST_FOREACH(Value const& v, result_n)
	//	std::cout << bg::wkt<DBox>(v.first) << " - " << v.second << std::endl;
}

//创建多边形
void boost_test5()
{
    typedef boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> Point;
    typedef boost::geometry::model::polygon<Point, false, false> Polygon; // ccw, open polygon

    //创建多边形
    Polygon p;
    for (float a = 0; a < 6.28316f; a += 1.04720f)
    {
        float x = int(10 * ::cos(a))*0.1f;
        float y = int(10 * ::sin(a))*0.1f;
        p.outer().push_back(Point(x, y));
    }
}

//创建多边形
void boost_test6()
{
    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; //矩形
                                         //这里的ring就是我们通常说的多边形闭合区域(内部不存在缕空),模板参数为true,表示顺时针存储点,为false,表示逆时针存储点,坐标系为正常向上向右为正的笛卡尔坐标系
    typedef bg::model::ring<DPoint, false> DRing; //环
    typedef bg::model::polygon<DPoint, false> DPolygon; //多边形
    #define A_PI 3.141592653589793238462643383279502884197

    //创建点
    DPoint pt1(0, 0), pt2(10, 10);

    //创建线段
    DSegment ds;
    ds.first = pt1;
    ds.second = pt2;

    //创建多段线
    DLineString dl;
    dl.push_back(DPoint(0, 0));
    dl.push_back(DPoint(15, 8));
    dl.push_back(DPoint(8, 13));
    dl.push_back(DPoint(13, 16));

    //创建矩形
    DBox db(pt1, pt2);

    //创建环
    DRing dr;
    dr.push_back(DPoint(0, 0));
    dr.push_back(DPoint(1, 2));
    dr.push_back(DPoint(3, 4));
    dr.push_back(DPoint(5, 6));

    //创建多边形
    DPolygon p;
    for (double a = 0; a < 2 * A_PI; a += 2 * A_PI / 18)
    {
        double x = ::cos(a)*10.0f;
        double y = ::sin(a)*10.0f;
        p.outer().push_back(DPoint(x, y));
    }
}

/*
如何让rtree用自己的数据。
看来最重要的操作是用indexable来让rtree知道,如何在你的结构体里得到point?
https://stackoverflow.com/questions/64179718/storing-or-accessing-objects-in-boost-r-tree
ou can store any type in a rtree, you just have to tell Boost how to get the coordinates out.

So the first step is to make a type with both a index and point:

struct CityRef {
size_t index;
point location;
};

You can specialize boost::geometry::index::indexable to give Boost a way to find the point you've put in there:

template <>
struct bgi::indexable<CityRef>
{
typedef point result_type;
point operator()(const CityRef& c) const { return c.location; }
};

Then you can use your type in place of point when declaring your rtree:

typedef bgi::rtree< CityRef, bgi::linear<16> > rtree_t;

And when you iterate, the iterator will refer to your type instead of point:

for ( rtree_t::const_query_iterator
it = rtree.qbegin(bgi::nearest(pt, 100)) ;
it != rtree.qend() ;
++it )
{
// *it is a CityRef, do whatever you want
}

Here is a demo using that example with another type: https://godbolt.org/z/zT3xcf


*/

namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
typedef bg::model::point<double, 2, bg::cs::cartesian> boostPoint2d;
struct CityRef {
    size_t index;
    double index2;
    boostPoint2d location;
    //rtree在插入数据以及检索时,没走到这个函数,说明rtree内部是用指针的
//     CityRef& operator = (const CityRef& r)
//     {
//         index = r.index;
//         index2 = r.index2;
//         location = r.location;
//         return *this;
//     }
    //rtree在插入数据以及检索时,没走到这个函数
//     bool operator == (const CityRef& r) const
//     {
//         bool b1 = index == r.index;
//         bool b2 = index2 == r.index2;
//         bool b3 = (location.get<0>() == r.location.get<0>() && 
//             location.get<1>() == r.location.get<1>());
// 
//         if (b1&&b2&&b3)
//             return true;
// 
//         return false;
//     }
};

template <>
struct bgi::indexable<CityRef>
{
    typedef boostPoint2d result_type; //这个不能缺少
    //boostPoint2d operator()(const CityRef& c) const { return c.location; }
    const boostPoint2d& operator()(const CityRef& c) const { return c.location; }
};

struct BoostTest7
{
    int DoTest() {
    typedef CityRef value;
    typedef bgi::rtree< value, bgi::linear<16> > rtree_t;

    // create the rtree using default constructor
    rtree_t rtree;

    // create some values
    for ( double f = 0 ; f < 10 ; f += 1 )
    {
        CityRef data;
        data.index = (static_cast<size_t>(f));
        data.index2 = f + 1;
        data.location.set<0>(f);
        data.location.set<1>(f);
        // insert new value
        rtree.insert(data);
        //rtree.insert({ static_cast<size_t>(f), f + 1,{ f, f } });
    }

    // query point
    boostPoint2d pt(5.1, 5.1);

    // iterate over nearest Values
    //根据距离从近到远
    /*
    index=5, index2=6.000000, (5.000000, 5.000000), distance=0.141421
    index=6, index2=7.000000, (6.000000, 6.000000), distance=1.272792
    index=4, index2=5.000000, (4.000000, 4.000000), distance=1.555635
    index=7, index2=8.000000, (7.000000, 7.000000), distance=2.687006break!
    */
    /*
    另外,这种写法的原因,是为了在满足数据条件后可以直接break。
    https://www.py4u.net/discuss/75145
    https://www.boost.org/doc/libs/1_55_0/libs/geometry/doc/html/geometry/spatial_indexes/queries.html#geometry.spatial_indexes.queries.breaking_or_pausing_the_query

    Breaking or pausing the query

    The query performed using query iterators may be paused and resumed if needed, e.g. when the query takes too long, or stopped at some point, e.g when all interesting values were gathered.

    for ( Rtree::const_query_iterator it = tree.qbegin(bgi::nearest(pt, 10000)) ;
    it != tree.qend() ; ++it )
    {
    // do something with value
    if ( has_enough_nearest_values() )
    break;
    }

    */
    for ( rtree_t::const_query_iterator
            it = rtree.qbegin(bgi::nearest(pt, 100)) ;
            it != rtree.qend() ;
            ++it )
    {
        double d = bg::distance(pt, it->location);
        //
        /*
        可以修改除了point之外的数据
        */
        CityRef& xx = const_cast<CityRef&>(*it);
        xx.index2 = 10;
        //std::cout << "index=" << it->index << ", " << bg::wkt(it->location) << ", distance= " << d << std::endl;
        wprintf(L"\n index=%d, index2=%f, (%f, %f), distance=%f", 
             it->index , 
            it->index2,
            it->location.get<0>() ,
            it->location.get<1>()
            , d );

        // break if the distance is too big
        if ( d > 2 )
        {
            std::cout << "break!" << std::endl;
            break;
        }
    }

    return 0;
}

};
void boostTest7()
{
    BoostTest7 o;
    o.DoTest();
 
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/915693.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序-prettier 格式化

一.安装prettier插件 二.配置开发者工具的设置 配置如下代码在setting.json里&#xff1a; "editor.formatOnSave": true,"editor.defaultFormatter": "esbenp.prettier-vscode","prettier.documentSelectors": ["**/*.wxml"…

【机器学习】数学知识:标准差,方差,协方差,平均数,中位数,众数

标准差、方差和协方差是统计学中重要的概念&#xff0c;用于描述数据的分散程度和变量之间的关系。以下是它们的定义和公式&#xff1a; 1. 标准差 (Standard Deviation) 标准差是方差的平方根&#xff0c;表示数据的分散程度&#xff0c;以与数据相同的单位表示。 公式&…

Redis8:商户查询缓存2

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

【QT常用技术讲解】优化网络链接不上导致qt、qml界面卡顿的问题

前言 qt、qml项目经常会涉及访问MySQL数据库、网络服务器&#xff0c;并且界面打开时的初始化过程就会涉及到链接Mysql、网络服务器获取数据&#xff0c;如果网络不通&#xff0c;卡个几十秒&#xff0c;会让用户觉得非常的不爽&#xff0c;本文从技术调研的角度讲解解决此类问…

HelloMeme 上手即用教程

HelloMeme是一个集成空间编织注意力的扩散模型&#xff0c;用于生成高保真图像和视频。它提供了一个代码库&#xff0c;包含实验代码和预训练模型&#xff0c;支持PyTorch和FFmpeg。用户可以通过简单的命令行操作来生成图像和视频。 本文将详细介绍&#xff0c;如何在GPU算力租…

公开一下我的「个人学习视频」!

哈喽&#xff0c;大家好&#xff0c;我是六哥。 鉴于上次分享&#xff0c;很多同学说&#xff0c;六哥能整一些百度网盘的资源吗&#xff1f; 可以&#xff0c;来安排&#xff0c;看看有你心动的吗&#xff1f; 性能测试系列 测开系列 python方向 Java方向 主管必会系列 质…

13.观察者模式设计思想

13.观察者模式设计思想 目录介绍 01.观察者模式基础 1.1 观察者模式由来1.2 观察者模式定义1.3 观察者模式场景1.4 观察者模式思考 02.观察者模式实现 2.1 罗列一个场景2.2 用例子理解观察者2.3 案例演变分析2.4 观察者模式基本实现 03.观察者模式分析 3.1 观察者模式案例3.2…

webpack指南

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;webpack篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来webpack篇专栏内容:webpack-指南 概念 中文&#xff1a; webpack | webpack中文文档 | webpack中文网 英文&…

CSS高级技巧_精灵图_字体图标_CSS三角_vertical-align(图像和文字居中在同一行)_溢出文字省略号显示

目录 CSS高级技巧 1. 精灵图 1.1 为什么需要精灵图 1.2 精灵图&#xff08;sprites&#xff09;的使用 1.2 精灵图的使用 案例&#xff1a;拼出自己名字 2. 字体图标 2.1 字体图标的产生 2.2 字体图标的优点 2.3 字体图标的下载 2.4 字体图标的引入 2.4.1 字体文件格…

仪表板展示|DataEase看中国:历年双十一电商销售数据分析

背景介绍 2024年“双十一”购物季正在火热进行中。自2009年首次推出至今&#xff0c;“双十一”已经成为中国乃至全球最大的购物狂欢节&#xff0c;并且延伸到了全球范围内的电子商务平台。随着人们消费水平的提升以及电子商务的普及&#xff0c;线上销售模式也逐渐呈现多元化…

若依项目-结构解读

项目结构 admin模块 common模块 framework模块 service模块 配置 依赖关系 前端接口 src 表结构

RTSP前端实时流

因项目需求探索前端实时流&#xff0c;本文介绍了 RTSP 前端不能直接播放&#xff0c;需中间层转换协议&#xff0c;如 RTSP 转 RTMP、HLS、HTTP-FLV&#xff0c;分别阐述其特点、配置和播放方式&#xff0c;还提及关键帧、延迟与卡顿的关系&#xff0c;以及直播平台使用云服务…

植物大战僵尸杂交版v2.6.1最新版本(附下载链接)

B站游戏作者潜艇伟伟迷于11月3日更新了植物大战僵尸杂交版2.6.1版本&#xff01;&#xff01;&#xff01;&#xff0c;有b站账户的记得要给作者三连关注一下呀&#xff01; 不多废话下载链接放上&#xff1a; 夸克网盘链接&#xff1a;https://pan.quark.cn/s/279e7ed9f878 新…

qsqlmysql.lib的编译和使用

文章目录 打开源码 打开源码 打开qt源码安装路径 src相对路径下的文件Src\qtbase\src\plugins\sqldrivers\mysql 比如我是5.9.9版本我的路径就是&#xff1a;D:\Qt5.9.9\5.9.9\Src\qtbase\src\plugins\sqldrivers\mysql 可以看到待编译的mysql驱动文件 使用IDE打开pro文件进…

Window下PHP安装最新sg11(php5.3-php8.3)

链接: https://pan.baidu.com/s/10yyqTJdwH_oQJnQtWcwIeA 提取码: qz8y 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 (链接失效联系L88467872) 1.下载后解压文件&#xff0c;将对应版本的ixed.xx.win文件放进php对应的ext目录下&#xff0c;如图所示 2.修改ph…

30.超市管理系统(基于springboot和Vue的Java项目)

目录 1.系统的受众说明 2.相关技术和开发环境 2.1 相关技术 2.1.1 Java语言 2.1.2 HTML、CSS、JavaScript 2.1.3 MySQL 2.1.4 Vue.js 2.1.5 SpringBoot 2.2 开发环境 3. 系统分析 3.1 可行性分析 3.1.1 经济可行性 3.1.2 技术可行性 3.1.3 运行可行性 3.2…

去地面算法——depth_clustering算法调试(1)

1 源码下载 论文&#xff1a; 《2016-Fast Range Image-Based Segmentation of Sparse 3D Laser Scans for Online Operation》 《2017-Efficient Online Segmentation for Sparse 3D Laser Scans》 代码&#xff1a;git链接 2 问题记录 2.1 无法找到qt问题 问题截图&…

pyspark入门基础详细讲解

1.前言介绍 学习目标&#xff1a;了解什么是Speak、PySpark&#xff0c;了解为什么学习PySpark&#xff0c;了解课程是如何和大数据开发方向进行衔接 使用pyspark库所写出来的代码&#xff0c;既可以在电脑上简单运行&#xff0c;进行数据分析处理&#xff0c;又可以把代码无缝…

Qt 编写插件plugin,支持接口定义信号

https://blog.csdn.net/u014213012/article/details/122434193?spm1001.2014.3001.5506 本教程基于该链接的内容进行升级&#xff0c;在编写插件的基础上&#xff0c;支持接口类定义信号。 环境&#xff1a;Qt5.12.12 MSVC2017 一、创建项目 新建一个子项目便于程序管理【…

【python】python使用虚拟环境

使用虚拟环境的好处是创建一个独立干净的环境 首先cd到新项目的目录下 创建虚拟环境 使用日期命名方便自己找到版本 python -m venv venv20241114激活虚拟环境 .\venv20241114\Scripts\activate会创建一个文件夹 点进去可以看到是python的脚本所存文件结构 纯净环境 p…