OsgEarth3基础3D图形实现

news2025/8/13 5:38:36

OsgEarth3基础3D图形实现

  • 主要难点
    • Geometry能力
    • 姿态支持
  • 任意立方体 PolygonCube
  • 矩形立方体 Box
  • 圆锥体 Cone
  • 圆柱体 Cylinder
  • 四棱锥 Pyramid
  • 球体 Sphere
  • 源码示例
    • ElementGeometry
    • 圆锥Cone

这里尝试在通过OsgEarth提供的各种图形绘制方法,实现基础的3D图形。每个图形除了基础的设置外,尝试提供:位置(Position)姿态(Posture)、**填充色(FillColor)、描边色(ProfileColor/LineColor)的设置,在具体的框架性代码环境中也可以尝试抽象出基类,这里主要关注具体实现。
在这里插入图片描述

主要难点

Geometry能力

其中osg::Geometry提供的顶点绘制能力,可以满足对各种形状的实现,所以这里也是为了绘制需要图形的描边线,进行了简单封装,通过提供顶点数组、顶点坐标、图形样式、线颜色、线宽完成绘制。

事实上它可以包含:

  1. Statetset信息:比如设置透明度支持:
m_pGeom->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
m_pGeom->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
  1. Primitive列表和顶点数组:确定顶点索引,添加多个几何体
    提供的几何体类型也很丰富,具体描述可以详见该博客

https://blog.csdn.net/qq_36881934/article/details/107912706

 enum Mode
 {
      POINTS = GL_POINTS,
      LINES = GL_LINES,
      LINE_STRIP = GL_LINE_STRIP,
      LINE_LOOP = GL_LINE_LOOP,
      TRIANGLES = GL_TRIANGLES,
      TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
      TRIANGLE_FAN = GL_TRIANGLE_FAN,
      QUADS = GL_QUADS,
      QUAD_STRIP = GL_QUAD_STRIP,
      POLYGON = GL_POLYGON,
      LINES_ADJACENCY = GL_LINES_ADJACENCY,
      LINE_STRIP_ADJACENCY = GL_LINE_STRIP_ADJACENCY,
      TRIANGLES_ADJACENCY = GL_TRIANGLES_ADJACENCY,
      TRIANGLE_STRIP_ADJACENCY = GL_TRIANGLE_STRIP_ADJACENCY,
      PATCHES = GL_PATCHES
};

有特殊顺序的可以通过顶点索引,设置顶点坐标的方式添加:

osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;//创建一个几何体对象

osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
v->push_back(osg::Vec3(2.0f, 0.0f, 0.0f));
v->push_back(osg::Vec3(1.0f, -1.0f, 1.0f));
v->push_back(osg::Vec3(2.0f, -2.0f, 0.0f));
v->push_back(osg::Vec3(0.0f, -2.0f, 0.0f));
geometry->setVertexArray(v);//设置几何体顶点数据

osg::ref_ptr<osg::DrawElementsUInt> quad = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP, 0);//指定绘图基元为绘制多段三角形
quad->push_back(0); quad->push_back(1); quad->push_back(2); 
quad->push_back(3); quad->push_back(4);  
quad->push_back(0); quad->push_back(2);
geometry->addPrimitiveSet(quad);//添加到几何体

简单的顶点连接顺序,可以直接通过geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, vcArray->size()));添加。

  1. 颜色/纹理数组列表
    颜色可以是渐变色,也可以是纯色,主要在于设置的颜色数组,以及颜色绑定模式。
    如渐变色可以根据顶点:

osg::ref_ptr<osg::Vec4Array> vc = new osg::Vec4Array;//创建颜色数组
vc->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
vc->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
vc->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
vc->push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
vc->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
geometry->setColorArray(vc);
geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);//设置颜色绑定模式

在这里插入图片描述

姿态支持

对于3D图形的属性,姿态肯定也是重点:俯仰、横滚、航向。
这里通过osg::MatrixTransform的rotate方式实现。
首先将Matrix加入到osgEarth::GeoTransform节点,Drawable加入到Matrix节点作为Child,就可以控制Drawable图形的姿态了。

// GeoTransform
	m_pGeoTransform = new osgEarth::GeoTransform();
	m_pMatrix = new osg::MatrixTransform;
	m_pGeoTransform->addChild(m_pMatrix);
	m_pMatrix->addChild(m_pDrawable);
m_pMatrix->setMatrix(
		osg::Matrix::rotate(
			osg::DegreesToRadians(vPos.x()), osg::X_AXIS,
			osg::DegreesToRadians(vPos.y()), osg::Y_AXIS,
			osg::DegreesToRadians(vPos.z()), osg::Z_AXIS));
}

在这里插入图片描述

任意立方体 PolygonCube

使用osgEarth::FeatureNode实现,它对矢量的点线面绘制提供了很好的解决方案,包括与地形的贴合方式(osgEarth::AltitudeSymbol::Clamping),与矢量图层的结合方式等。这里主要通过设置一组坐标信息,绘制立方体。
在这里插入图片描述

矩形立方体 Box

虽然osgEarth::FeatureNode通过设置顶点坐标,也可以画出矩形立方体,但是在实践的过程中发现,高度实现,更准确讲是实现的面向上“挤出”后的效果,而且地面没有封顶,也没有描边线。

m_Style.getOrCreate<ExtrusionSymbol>()->height() = dHeightMeter;

为了实现一个“像样的”矩形立方体,使用了osg::Box结合osg::ShapeDrawable实现,但是osg的绘制体没有描边色,所以也是通过osg::Geometry实现了Box的边线。
在这里插入图片描述

圆锥体 Cone

使用了osg::Cone结合osg::ShapeDrawable实现,也是通过osg::Geometry实现了底部圆形描边+分段线描边。
注意中心点在高度的1/3处,所以如果要控制中心点在底部,可以通过让osgEarth::GeoTransform->addChild(),加入一个Relative的osg::MatrixTransform去偏移到底部。
在这里插入图片描述

圆柱体 Cylinder

使用了osg::Cylinder结合osg::ShapeDrawable实现,也是通过osg::Geometry实现了上下圆形描边+分段线描边。
另一个重点是,Cylinder的实现最开始我是尝试的osgEarth::CircleNode,也可以达到圆柱的效果,但是没办法自己控制分段线的条数,也不能直接根据Matrix修改姿态,高度也是“挤出”形式,也是为了统一内部实现,改为了现在的osg::Cylinder,虽然分段线多一点点实现过程,但效果会更好。
注意中心点在高度的1/2处,所以如果要控制中心点在底部,可以通过让osgEarth::GeoTransform->addChild(),加入一个Relative的osg::MatrixTransform去偏移到底部。
在这里插入图片描述

四棱锥 Pyramid

这个图形,可以说是“纯手工”绘制,因为图形和描边线,都是用的osg::Geometry实现,osg::Geometry通过addPrimitiveSet两个顶点数组索引,完成实现。
最开始没有理解到osg::Geometry的精髓,使用了两个osg::Geometry分别实现三角面和连线,事实上addPrimitiveSet已经给出了解决方案,已经把图形组的接口给抽象好了。
重要代码:

	{
		osg::ref_ptr<osg::DrawElementsUInt> quad = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP, 0);//指定绘图基元为绘制多段三角形
		quad->push_back(0); quad->push_back(1); quad->push_back(2);
		quad->push_back(3); quad->push_back(0); quad->push_back(4);
		quad->push_back(1); quad->push_back(4); quad->push_back(2); quad->push_back(3);
		m_pGeometry->addPrimitiveSet(quad);//添加到几何体
	}


	{
		osg::ref_ptr<osg::DrawElementsUInt> quad = new osg::DrawElementsUInt(osg::PrimitiveSet::LINE_LOOP, 0);//指定绘图基元为绘制闭合线
		quad->push_back(0); quad->push_back(1); quad->push_back(2);
		quad->push_back(3); quad->push_back(4); quad->push_back(0); 
		quad->push_back(4); quad->push_back(1); quad->push_back(2); quad->push_back(4); quad->push_back(3);
		m_pGeometry->addPrimitiveSet(quad);//添加到几何体
	}

	// Color
	m_cSurface = Color::White;
	m_cLine = Color(0, 0, 0, 0);
	m_vcColor = new osg::Vec4Array;
	m_vcColor->push_back(m_cSurface);
	m_vcColor->push_back(m_cLine);
	m_pGeometry->setColorArray(m_vcColor, osg::Array::BIND_PER_PRIMITIVE_SET);
	m_pGeometry->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
	m_pGeometry->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

void CPyramidObject3D::Rebuild()
{
	if (NULL == m_vcGeom)
	{
		return;
	}

	m_vcGeom->clear();

	m_vcGeom->push_back(osg::Vec3d(-m_dX/2, -m_dY/2, 0.0));
	m_vcGeom->push_back(osg::Vec3d(-m_dX/2, m_dY/2, 0.0));
	m_vcGeom->push_back(osg::Vec3d(m_dX/2, m_dY/2, 0.0f));
	m_vcGeom->push_back(osg::Vec3d(m_dX/2, -m_dY/2, 0.0));
	m_vcGeom->push_back(osg::Vec3d(0.0, 0.0, m_dH));

	m_pGeometry->setVertexArray(m_vcGeom);
}

球体 Sphere

使用了osg::Sphere结合osg::ShapeDrawable实现,也是通过osg::Geometry实现了横竖的分段线绘制。主要是对于球体,需要有分段线才能体现立体感,否则和2D圆形的区别在某些角度就不明显了。
在这里插入图片描述


源码示例

3D图形的实现源码之前分享过一次,这次为了描边线和姿态又尝试修改了一些实现,具体的环境搭建,可以看上一篇文章。
有一些实现不足的多多指教,对于OsgEarth的学习也在摸索中。

  1. 封装基于Osg+OsgEarth3实现的3D基础图元类,每个类提供各个图元的基础参数设置。
  2. 封装的图元类:PolygonCubeObject3D(任意立方体)、CylinderObject3DEx(圆柱)、SphereObject3D(球体)、ConeObject3D(圆锥)、PyramidObject3D(四棱锥)、BoxObject3D(矩形立方体)。
  3. OsgEarthMapViewer内包含响应按钮事件(hand函数),以动态修改图元属性的测试。注意测试指定图元属性修改时,需要打开指定handle的注释,并对应switch内的按键进行操作。
  4. 建议自行建立工程后,编译源码后进行测试(内含main.cpp),随时修改以及时看到变化情况,了解各个参数对绘制的影响。
    (相比上面的2D图元绘制的代码,3D图元绘制的资源内,封装了对绘制属性的设置修改,即封装成类,提供到接口操作)
    在这里插入图片描述

这里提供ElementGeometry和Cone的示例实现,其它的就是依葫芦画瓢了。

ElementGeometry

为了其它图元内部更好地实现描边线而进行的封装

#ifndef ElementGeometry_h__
#define ElementGeometry_h__

#include <osg/Node>
#include <osgEarth/SpatialReference>
#include <osgEarth/Color>
#include <osgEarth/GeoTransform>
#include <osg/Geometry>
#include <osg/LineWidth>

class CElementGeometry
{
public:
	CElementGeometry();
	~CElementGeometry();

	osg::ref_ptr<osg::Geometry> GetGeometry() const;

	void SetVertexArray(osg::Vec3Array* array);

	void AddPrimitiveSet(osg::PrimitiveSet* quad);

	void RemovePrimitiveSet(int nIndex);

	void SetColor(const osgEarth::Color& c);

	void SetColorArray(osg::Array* array, osg::Array::Binding binding);

	void SetWidth(float fWidth);

private:

	osg::ref_ptr<osg::Geometry> m_pGeom;
	osg::ref_ptr<osg::LineWidth> m_pLineWidth;
};

#endif // ElementGeometry_h__

#include "ElementGeometry.h"

CElementGeometry::CElementGeometry()
{
	m_pGeom = new osg::Geometry;
	m_pGeom->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
	m_pGeom->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}

CElementGeometry::~CElementGeometry()
{
	m_pGeom = NULL;
}

osg::ref_ptr<osg::Geometry> CElementGeometry::GetGeometry() const
{
	return m_pGeom;
}

void CElementGeometry::SetVertexArray(osg::Vec3Array* array)
{
	m_pGeom->setVertexArray(array);
}

void CElementGeometry::AddPrimitiveSet(osg::PrimitiveSet* quad)
{
	m_pGeom->addPrimitiveSet(quad);
}

void CElementGeometry::RemovePrimitiveSet(int nIndex)
{
	m_pGeom->removePrimitiveSet(nIndex);
}

void CElementGeometry::SetColor(const osgEarth::Color& c)
{
	osg::Vec4Array* vecColorSurface = new osg::Vec4Array;
	vecColorSurface->push_back(c);
	m_pGeom->setColorArray(vecColorSurface, osg::Array::BIND_OVERALL);
}

void CElementGeometry::SetColorArray(osg::Array* array, osg::Array::Binding binding)
{
	m_pGeom->setColorArray(array, binding);
}

void CElementGeometry::SetWidth(float fWidth)
{
	if (fWidth > 0.0)
	{
		if (!m_pLineWidth.valid())
		{
			m_pLineWidth = new osg::LineWidth(1.0f);
			m_pGeom->getOrCreateStateSet()->setAttribute(m_pLineWidth, osg::StateAttribute::OFF);
		}

		m_pLineWidth->setWidth(fWidth);
		m_pGeom->setNodeMask(0xff);
	}
	else
	{
		m_pGeom->setNodeMask(0);
	}

	m_pGeom->dirtyDisplayList();
}


圆锥Cone

#ifndef ConeObject3D_h__
#define ConeObject3D_h__

#include <osg/Node>
#include <osg/ShapeDrawable>
#include <osg/Shape>
#include <osgEarth/SpatialReference>
#include <osgEarth/Color>
#include <osgEarth/GeoTransform>

class CElementGeometry;
class CConeObject3D
{
public:
	CConeObject3D(const osgEarth::SpatialReference* mapSRS);
	~CConeObject3D();

	osg::ref_ptr<osg::Node> GetObjectNode() const;

	void SetCenter(const osg::Vec3d& vPt);

	void SetRadius(double dRadiusMeter);

	void SetHeight(double dHeightMeter);

	void SetPosture(const osg::Vec3d& vPos);

	void SetFillColor(const osgEarth::Color& c);

	void SetProfileColor(const osgEarth::Color& c);

	void SetProfileWidth(float dWidth);

	void SetSegmentation(int nNum);

private:

	void BuildProfile(double dRadius, double dHeight, int nNum);

private:
	const osgEarth::SpatialReference* m_pSRS;

	osg::ref_ptr<osgEarth::GeoTransform> m_pGeoTransform;
	osg::ref_ptr<osg::MatrixTransform> m_pMatrix;
	osg::ref_ptr<osg::MatrixTransform> m_pRelativeMatrix;
	osg::Vec3d m_vPosture;

	osg::ShapeDrawable* m_pDrawable;
	osg::Cone* m_pCone;

	double m_dRadius;
	double m_dHeight;
	osgEarth::Color m_lineColor;
	float m_fLineWidth;

	std::vector<CElementGeometry*> m_vecGeometry;
};

#endif // ConeObject3D_h__

#include "ConeObject3D.h"
#include "osg/Math"
#include "ElementGeometry.h"

using namespace osgEarth;

CConeObject3D::CConeObject3D(const osgEarth::SpatialReference* mapSRS)
	: m_pSRS(mapSRS)
	, m_dRadius(0.0)
	, m_dHeight(0.0)
	, m_fLineWidth(0.0)
{
	m_pCone = new osg::Cone();

	m_pDrawable = new osg::ShapeDrawable(m_pCone);
	m_pDrawable->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
	m_pDrawable->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

	m_pGeoTransform = new osgEarth::GeoTransform();
	m_pMatrix = new osg::MatrixTransform;
	m_pRelativeMatrix = new osg::MatrixTransform;
	m_pGeoTransform->addChild(m_pMatrix);
	m_pMatrix->addChild(m_pDrawable);
	m_pMatrix->addChild(m_pRelativeMatrix);

	SetRadius(5000);
	SetHeight(1000);
}

CConeObject3D::~CConeObject3D()
{
	SetSegmentation(-1);
	m_pGeoTransform = NULL;
}

osg::ref_ptr<osg::Node> CConeObject3D::GetObjectNode() const
{
	return m_pGeoTransform;
}

void CConeObject3D::SetCenter(const osg::Vec3d& vPt)
{
	m_pGeoTransform->setPosition(osgEarth::GeoPoint(m_pSRS, vPt, osgEarth::ALTMODE_RELATIVE));
}

void CConeObject3D::SetRadius(double dRadiusMeter)
{
	m_pCone->setRadius(dRadiusMeter);

	m_pDrawable->dirtyDisplayList();
	m_pGeoTransform->dirtyBound();

	m_dRadius = dRadiusMeter;

	SetSegmentation(m_vecGeometry.size() - 1);
}

void CConeObject3D::SetHeight(double dHeightMeter)
{
	m_dHeight = dHeightMeter;
	m_pCone->setHeight(dHeightMeter);

	// 原始中心点在图形中间 h的1/4处
	m_pRelativeMatrix->setMatrix(
		osg::Matrix::rotate(0.0, osg::X_AXIS,
			0.0, osg::Y_AXIS,
			0.0, osg::Z_AXIS)
		*osg::Matrix::translate(osg::Vec3d(0, 0, -dHeightMeter / 4)));
	SetPosture(m_vPosture);

	m_pDrawable->dirtyDisplayList();
	m_pGeoTransform->dirtyBound();


	SetSegmentation(m_vecGeometry.size() - 1);
}

void CConeObject3D::SetPosture(const osg::Vec3d& vPos)
{
	m_vPosture = vPos;

	m_pMatrix->setMatrix(
		osg::Matrix::rotate(
			osg::DegreesToRadians(vPos.x()), osg::X_AXIS,
			osg::DegreesToRadians(vPos.y()), osg::Y_AXIS,
			osg::DegreesToRadians(vPos.z()), osg::Z_AXIS)
		*osg::Matrix::translate(osg::Vec3d(0, 0, m_dHeight / 4)));
}

void CConeObject3D::SetFillColor(const osgEarth::Color& c)
{
	m_pDrawable->setColor(c);
}

void CConeObject3D::SetProfileColor(const osgEarth::Color& c)
{
	for (int i = 0; i < m_vecGeometry.size(); i++)
	{
		m_vecGeometry[i]->SetColor(c);
	}
	m_lineColor = c;
}

void CConeObject3D::SetProfileWidth(float dWidth)
{
	for (int i = 0; i < m_vecGeometry.size(); i++)
	{
		m_vecGeometry[i]->SetWidth(dWidth);
	}
	m_fLineWidth = dWidth;
}

void CConeObject3D::SetSegmentation(int nNum)
{
	for (int i = 0; i < m_vecGeometry.size(); i++)
	{
		m_pRelativeMatrix->removeChild(m_vecGeometry[i]->GetGeometry());
	}
	m_vecGeometry.clear();

	BuildProfile(m_dRadius, m_dHeight, nNum);
	SetProfileWidth(m_fLineWidth);
	SetProfileColor(m_lineColor);
}

// ===== Private

void CConeObject3D::BuildProfile(double dRadius, double dHeight, int nNum)
{
	if (nNum < 0)
	{
		return;
	}

	// circle
	{
		osg::ref_ptr<osg::Vec3Array> vcArray = new osg::Vec3Array;
		int n = pow(2.0, 7);
		double dAngle = 360.0 / n;
		for (int i = 0; i < n; i++)
		{
			double dTmpAngle = dAngle * i;
			double dRad = dTmpAngle * (osg::PI / 180);

			double dX = dRadius * cos(dRad);
			double dY = dRadius * sin(dRad);
			vcArray->push_back(osg::Vec3d(dX, dY, 0.0));
		}

		CElementGeometry* pElement = new CElementGeometry;
		pElement->SetVertexArray(vcArray);
		pElement->AddPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, vcArray->size()));
		m_vecGeometry.push_back(pElement);
		m_pRelativeMatrix->addChild(pElement->GetGeometry());
	}

	// lines
	if (nNum > 0)
	{
		double dAngle = 360.0 / nNum;
		for (int i = 0; i < nNum; i++)
		{
			double dTmpAngle = dAngle * i;
			double dRad = dTmpAngle * (osg::PI / 180);
			double dX = dRadius * cos(dRad);
			double dY = dRadius * sin(dRad);

			osg::ref_ptr<osg::Vec3Array> vcArray = new osg::Vec3Array;
			vcArray->push_back(osg::Vec3d(0.0, 0.0, dHeight));
			vcArray->push_back(osg::Vec3d(dX, dY, 0.0));

			CElementGeometry* pElement = new CElementGeometry;
			pElement->SetVertexArray(vcArray);
			pElement->AddPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, vcArray->size()));
			m_vecGeometry.push_back(pElement);
			m_pRelativeMatrix->addChild(pElement->GetGeometry());
		}
	}
}


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

推荐一个非常实用的程序员导航网站,码农必备!

这是一个非常好用的程序员导航网站&#xff0c;拥有该网站&#xff0c;就拥有一站式导航&#xff0c;再也不用为找网址而发愁了&#xff01; 先直接上网址&#xff1a;https://hao.panziye.com/ 现在来说说为什么推荐该程序员导航网站&#xff01; 1、支持自定义导航网址 该…

pytorch的安装教程

1. 官网 pytorch.org 哎呀呀呀&#xff0c;这是嘛呀哪里有download的按钮啊 别急 &#xff0c;往下拉就ok了哈哈 得看你自己电脑的配置了&#xff0c;自己选就行 、、注意哦 我们得复制一条指令 、 有anaconda的吧 在自己想要的环境里面 黏贴就行 有了 pytorch 可以干嘛呢…

Electron:BrowserView使用方法

我们知道&#xff0c;使用BrowserWindow来创建一个新的窗口&#xff0c;那么如果想在窗口中战胜斯更多的web内容&#xff0c;比如嵌入其他网站的内容&#xff0c;那就使用BrowserView了。 BrowserView的位置是相对于父窗口&#xff0c;比如&#xff1a; 代码如下&#xff1a;…

python项目使用pyinstaller打包

一、安装pyinstaller 打包要使用pyinstaller,使用pip来安装一下这个第三方库,打开命令行输入pip install pyinstaller 二、打包含有多个文件的python项目 1、首先打开电脑的cmd命令行,并切换到项目的根目录 项目路径输入cmd回车,可直接打开含有项目路径的cmd窗口 2、…

【推荐系统】行列式点过程(DPP)算法推导

一、背景 推荐系统主要解决用户和物品之间的相关性&#xff0c;以及推荐列表的多样性。相关性主要通过用户兴趣和物品之间的匹配程度来衡量&#xff0c;希望把用户感兴趣的物品推荐给用户&#xff0c;可以通过CTR预估模型来构建。多样性的衡量没有那么直观&#xff0c;一种方法…

std::unique_ptr(基础和仿写)

目录 一、C参考手册说明 1、解释注释 2、 参考代码 二、对std::unique_ptr分析 1、创建一个unique_ptr 2、无法进行复制构造和赋值操作 3、可以进行移动赋值 4.可以返回unique——ptr 5、管理动态数组 6、在容器中保存指针 三、对std::unique_ptr设计 1、对于的那个…

关于生命周期的面试题vue

1.第一次进入到页面&#xff08;组件&#xff09;会执行哪些生命周期 beforeCreate 》 没有data&#xff0c;没有elcreated 》 有data&#xff0c;没有elbeforeMount 》 有data&#xff0c;没有el&#xff08;其实已经在准备了&#xff09;mounted 》 有data&#xff0c;有el …

SRM供应商管理系统有什么作用?

目前国内稍具规模的企业都导入了企业资源管理ERP系统&#xff0c;实现了内部管理数字化转型&#xff0c;提升了内部各部门之间的协同能力。但是企业供应链管理涉及大量的外部资源&#xff0c;特别是数量庞大的供应商资源&#xff0c;而大部分的ERP系统很难实现采购同供应商之间…

感恩节,感谢2022的转变,有在好好生活!

疫情之下的感恩节 原来今天是感恩节。2022年快要结束了&#xff0c;在这样一个特别的节日里&#xff0c;就不写技术类文章了&#xff0c;写一写我的2022年&#xff0c;这一年&#xff0c;我的学习、工作和生活都有发生改变&#xff0c;感谢过去的时光&#xff0c;改变让我有在…

Linux下:文件与路径、用户管理、常用命令、vim

文章目录第一章&#xff1a; Linux文件与路径1.1 文件结构1.2 基本概念1.3 基本命令信息1.3.1 查看linux 系统信息&#xff08;修改主机名&#xff09;1.3.2 ls1.3.3 cd/pwd1.3.4 pushd命令创建目录栈 第二章&#xff1a; 文件/目录的创建、删除、复制、阅读2.1 mkdir2.2 touc…

书籍Java8 实战 笔记

第5章 使用流 本章内容 1.筛选、切片和匹配 2.查找、匹配和归约 3.使用数值范围等数值流 4.从多个源创建流 5.无限流 5.1 筛选和切片 用谓词筛选&#xff0c;筛选出各不相同的元素&#xff0c;忽略流中的头几个元素&#xff0c;或将流截短至指定长度。 5.1.1 用谓词筛选 就是…

【优化分配】粒子群算法求解火车票分配优化问题【含Matlab源码 1137期】

⛄一、粒子群算法简介 1 引言 自然界中的鸟群和鱼群的群体行为一直是科学家的研究兴趣所在。生物学家Craig Reynolds在1987年提出了一个非常有影响的鸟群聚集模型&#xff0c;在他的仿真中&#xff0c;每一个个体都遵循&#xff1a;避免与邻域个体相撞&#xff1a;匹配邻域个体…

vue3+vite中使用vuex

前言&#xff1a; 在vue3vite创建的项目中使用vuex&#xff0c;要注意的是vite有部分写法和之前的webpack是不同的&#xff0c;比如&#xff0c;他不支持 require&#xff0c;想把vue2的项目直接升级到vue3的时候&#xff0c;需要改很多地方&#xff0c;如果非要使用vite也可以…

Caffeine《二》

《Caffeine&#xff08;Java顶级缓存组件&#xff09;二》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《Caffeine&#xff08;Java顶级缓存组件&#xff09;》《Caffeine&#xff08;Java顶级缓存组件&#xff09;二》8. 缓存驱逐算法8.1 FIFO(First …

ThingsBoard源码解析-设备连接

整体流程 在MqttTransportHandler中进行Mqtt消息处理&#xff0c;以AccessToken认证的设备举例&#xff0c;核心处理流程如下&#xff1a; //MqttTransportHandler 132 processMqttMsg(ctx, (MqttMessage) msg); //MqttTransportHandler 154 processConnect(ctx, (MqttConne…

视频文件转换器有哪些?什么视频文件转换器好用?

视频承载着丰富的文字、声音、图像&#xff0c;能够多维度地调用人的感知能力&#xff0c;可以说是当今时代信息输入的重要载体。 而视频有avi、rm、rmvb、3 gp等多种格式&#xff0c;当我们使用不同设备来观看视频时&#xff0c;就涉及到视频文件格式转换这一问题&#xff0c;…

RabbitMQ系列【14】备份交换机

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 文章目录前言代码实现测试前言 在之前&#xff0c;我们分析了消息可靠性之发布确认、退回机制。当消息到达交换机后&#xff0c;但是没有找到匹配的队列时&#xff0c;退回模式&#xff08;return&…

ms10-046漏洞利用+bypassuac提权

目录 前期准备 漏洞利用 上传文件到目标主机 UAC介绍 使用bypassuac模块绕过uac进行提权。 关于钓鱼链接的拓展 前期准备 Win xp sp3关闭防火墙 实验前提 保证连通性&#xff0c;进行互ping 漏洞利用 进入msf查看需要利用的漏洞&#xff1a;ms10-046 search ms10-046 …

【Kafka】单分区单副本增加至多分区多副本

一、背景 系统&#xff1a;CentOS Linux release 7.9.2009 (Core) Kafka版本&#xff1a;2.11-2.0.0.3.1.4.0-315 [scala版本2.11&#xff1b;kafka 2.0.0版本&#xff1b;基于ambari3.1.4.0-315的版本 ] 二、现象 业务系统中总是报警&#xff1a;kafka消费延迟。 三、问题…

nodejs+vue+elementui线上买菜系统

本线上买菜系统主要包括三大功能模块&#xff0c;即管理员和用户。 &#xff08;1&#xff09;管理员模块&#xff1a;首页、个人中心、用户管理、商品分类管理、商品信息管理、系统管理、订单管理。 &#xff08;2&#xff09;前台&#xff1a;商品信息、公告信息、个人中心、…