OpenCASCADE开发指南<十二>:OCC创建三维瓶子模型

  在OpenCASCADE有一个例程,在 官方帮助网站中可以找到。程将教你如何使OpenCASCADE的API来进行三维建模。教程的目的不是描述所有的类,而是帮助你思考如何将OpenCASCADE作为一种工具。

1 概述

  利用OpenCASCADE的API创建一个三维瓶子,形状如下图所示:

在这里插入图片描述

在这里插入图片描述
  瓶子的底座将以笛卡尔坐标系的原点为中心,规格设定如下:

物件参数	参数名称	 参数值
瓶子高度	myHeight	 70mm
瓶子宽度	myWidth	     50mm
瓶子厚度	myThickness	 30mm

2 瓶子建模步骤

2.1 构建轮廓

2.1.1 定义支持点

  首先创建轮廓的特征点及其坐标,如下面的(XOY)平面所示。这些点为瓶身几何形状一半的支持点。因为瓶子是对称的,因此另一半后面我们通过镜像可以得到。
在这里插入图片描述

    // 轮廓:定义支持点
	gp_Pnt aPnt1(-myWidth / 2., 0, 0);
	gp_Pnt aPnt2(-myWidth / 2., -myThickness / 4., 0);
	gp_Pnt aPnt3(0, -myThickness / 2., 0);
	gp_Pnt aPnt4(myWidth / 2., -myThickness / 4., 0);
	gp_Pnt aPnt5(myWidth / 2., 0, 0);
2.1.1 定义几何图形

  在前面定义的点的帮助下,您可以计算出瓶子轮廓几何的一部分。如图所示,它将由两个线段和一个圆弧组成。
在这里插入图片描述

    // 轮廓:定义几何图形
	Handle(Geom_TrimmedCurve) anArcOfCircle = GC_MakeArcOfCircle(aPnt2, aPnt3, aPnt4);
	Handle(Geom_TrimmedCurve) aSegment1 = GC_MakeSegment(aPnt1, aPnt2);
	Handle(Geom_TrimmedCurve) aSegment2 = GC_MakeSegment(aPnt4, aPnt5);
2.1.2 定义拓扑结构

  现在已经创建了轮廓的一个部分的几何曲线,但这些曲线是独立的,彼此之间没有关系。为了简化建模,可以凭借这三条曲线制作为一个实体。这可以通过使用TopoDS包中定义的OCC的拓扑数据结构来实现:它定义了几何实体之间的关系,这些实体可以链接在一起来表示复杂的形状。TopoDS包的每个对象继承自TopoDS_Shape类,描述一个拓扑形状,如下图所示:
在这里插入图片描述
  参照上表,要构建轮廓需要创建: 1)之前创建的三条边(Edge); 2)一条包含这些边的线框(Wire)。

  然而,TopoDS包只提供拓扑实体的数据结构。我们可以在BRepBuilderAPI包中找到用于计算标准拓扑对象的算法类。要创建一条线框(Wire),可以使用BRepBuilderAPI_MakeEdge类来创建前面计算过的曲线,用BRepBuilderAPI_MakeWire类来创建线框(Wire)。

// 轮廓:定义拓扑结构
TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aSegment1);
TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(anArcOfCircle);
TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(aSegment2);
TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3);
2.1.2 完成轮廓

  完成创建以上的线后,需要完成整个轮廓: 1)通过反射现有的导线来计算新的线;2)将反射线添加到初始线。
在这里插入图片描述

    // 轮廓:完成轮廓
	gp_Ax1 xAxis = gp::OX();    // 获得X轴
	gp_Trsf aTrsf;
	aTrsf.SetMirror(xAxis);
	BRepBuilderAPI_Transform aBRepTrsf(aWire, aTrsf);
	TopoDS_Shape aMirroredShape = aBRepTrsf.Shape();
	TopoDS_Wire aMirroredWire = TopoDS::Wire(aMirroredShape);
	BRepBuilderAPI_MakeWire mkWire;
	mkWire.Add(aWire);
	mkWire.Add(aMirroredWire);
	TopoDS_Wire myWireProfile = mkWire.Wire();

2.2 构建瓶身

2.2.1 拉伸轮廓

  要计算瓶身,需要创建一个实体形状。最简单的方法是使用前面创建的轮廓,并沿着一个方向进行扫描。Open CASCADE的Prism功能最适合这项任务。它接受一个形状和一个方向作为输入,并根据以下规则生成一个新的形状:
在这里插入图片描述
在这里插入图片描述

// 瓶身:拉伸轮廓
TopoDS_Face myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile);
gp_Vec aPrismVec(0, 0, myHeight);
TopoDS_Shape myBody = BRepPrimAPI_MakePrism(myFaceProfile, aPrismVec);
2.2.2 倒角

  由于瓶身的边缘很锋利,因此要用圆弧棱替换它们,可以使用OpenCASCADE的圆角功能。根据我们的需求,指定倒角必须:1)应用在形状的所有边缘; 2)半径是myThickness / 12。
在这里插入图片描述

    // 瓶身:倒角
	BRepFilletAPI_MakeFillet mkFillet(myBody);
	TopExp_Explorer anEdgeExplorer(myBody, TopAbs_EDGE);
	while (anEdgeExplorer.More()) 
	{
		TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExplorer.Current());
		//Add edge to fillet algorithm
		mkFillet.Add(myThickness / 12., anEdge);
		anEdgeExplorer.Next();
	}
	myBody = mkFillet.Shape();
2.2.3 添加瓶颈

  要在瓶子上加一个颈,需要做一个圆柱体,然后把它和瓶身融合在一起。圆柱体安装在瓶身的顶部,半径为myThickness / 4,高度为myHeight / 10。
在这里插入图片描述

    // 瓶身:添加瓶颈
	gp_Pnt neckLocation(0, 0, myHeight);
	gp_Dir neckAxis = gp::DZ();
	gp_Ax2 neckAx2(neckLocation, neckAxis);
	Standard_Real myNeckRadius = myThickness / 4.;
	Standard_Real myNeckHeight = myHeight / 10.;
	BRepPrimAPI_MakeCylinder MKCylinder(neckAx2, myNeckRadius, myNeckHeight);
	TopoDS_Shape myNeck = MKCylinder.Shape();
	myBody = BRepAlgoAPI_Fuse(myBody, myNeck);
2.2.4 创造中空的实体

  因为一个真正的瓶子是用来装液体材料的,所以应该从瓶子的顶部创建一个中空的实体。在OpenCASCADE中,被掏空的固体称为Thick Solid,其内部计算如下:

1)从初始实体中移除一个或多个面,以获得被掏空实体的第一面墙W1。
2)在距离D处,从W1创建一个平行的墙W2。如果D是正的,W2将在初始实体的外面,否则它将在里面。
3)从W1和W2两面墙计算一个实体。
在这里插入图片描述

    // 瓶身:创造中空的实体
	TopoDS_Face faceToRemove;
	Standard_Real zMax = -1;
	for (TopExp_Explorer aFaceExplorer(myBody, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next())
	{
		TopoDS_Face aFace = TopoDS::Face(aFaceExplorer.Current());
		// Check if <aFace> is the top face of the bottle's neck
		Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
		if (aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane)) 
		{
			Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface);
			gp_Pnt aPnt = aPlane->Location();
			Standard_Real aZ = aPnt.Z();
			if (aZ > zMax) {
				zMax = aZ;
				faceToRemove = aFace;
			}
		}
	}
	TopTools_ListOfShape facesToRemove;
	facesToRemove.Append(faceToRemove);
	BRepOffsetAPI_MakeThickSolid BodyMaker;
	BodyMaker.MakeThickSolidByJoin(myBody, facesToRemove, -myThickness / 50, 1.e-3);
	myBody = BodyMaker.Shape();

2.3 制作瓶口螺纹

2.3.1 创建表面

  接下来将学习如何创建一个二维曲线和曲面的边缘,以便在圆柱表面创建螺旋形轮廓。这个理论比前面的步骤更复杂,但是应用起来非常简单。

1)计算创建这些圆柱面。创建一个圆柱面(Geom_CylindricalSurface),需要使用:一个坐标系统和一个半径。

2)使用相同的坐标系统neckAx2用于定位颈部,创建两个具有以下半径的圆柱形表面Geom_CylindricalSurface:
在这里插入图片描述

Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);
Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);
2.3.2 定义二维曲线

  要创建瓶口,需要基于圆柱面制作一个实心圆柱体。通过表面上创建2D曲线来创建螺纹的轮廓。Geom包中定义的所有几何图形都是参数化的。这意味着Geom中的每条曲线或曲面都是用参数方程计算的。用以下参数方程定义Geom_CylindricalSurface:
P(U, V) = O + R * (cos(U) * xDir + sin(U) * yDir) + V * zDir,其中:

  • P是由参数(U, V)定义的点
  • O、xDir、yDir、zDir分别是柱面局部坐标系的原点、X方向、Y方向和Z方向
  • R是圆柱表面的半径
  • U的取值范围是[0,2π],且V是无穷大的
    在这里插入图片描述

这样进行几何参数化的优点是可以计算任何(U, V)的表面参数:

  • 三维点
  • 该点1,2到N阶的导数向量

参数化方程的另一个优点是可以把一个曲面看作是一个二维参数空间,它由(U, V)坐标系定义。例如,考虑颈部表面的参数范围:
在这里插入图片描述

假设在这个参数(U, V)空间上创建一条2D线,并计算它的3D参数曲线。根据行定义,结果如下:
在这里插入图片描述

    // 螺纹:定义二维曲线
	gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.);
	gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.);
	gp_Ax2d anAx2d(aPnt, aDir);
	Standard_Real aMajor = 2. * M_PI;
	Standard_Real aMinor = myNeckHeight / 10;
	Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);
	Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4);
	Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI);
	Handle(Geom2d_TrimmedCurve) anArc2 = new Geom2d_TrimmedCurve(anEllipse2, 0, M_PI);
	gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0);
	gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI);
	Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2);
2.3.3 创建边和线

  创建瓶子的基础轮廓,需要: 1)计算颈部螺纹的边缘;2)从这些边中计算出两条线。

在这里插入图片描述

    // 螺纹:创建边和线
	TopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1);
	TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1);
	TopoDS_Edge anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2);
	TopoDS_Edge anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment, aCyl2);
	TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1);
	TopoDS_Wire threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2, anEdge2OnSurf2);
	BRepLib::BuildCurves3d(threadingWire1);
	BRepLib::BuildCurves3d(threadingWire2);
2.3.4 构建螺纹

  螺纹将是一个实体形状,所以现在必须计算这些线的面,这些面允许您连接这些线,这些面的外壳,然后是实体本身。这可能是一个漫长的操作。在定义基本拓扑时,总是有更快的方法来构建实体。现在可以通过用两条线创造一个实体,OpenCASCADE提供了一种快速的方法来实现这一点,通过建立loft:一个外壳或固体在给定的序列中穿越一组线。loft函数是在BRepOffsetAPI_ThruSections类中实现的,使用方法如下:

  1. 通过创建类的实例初始化算法。如果要创建实体,必须指定此构造函数的第一个参数。默认情况下BRepOffsetAPI_ThruSections构建一个外壳。
  2. 使用AddWire方法添加连续的连接。
  3. 使用CheckCompatibility方法激活检查是否有相同数量的边的选项。在本例中,线里各有两条边,因此可以禁用此选项
  4. 用Shape方法求出loft形状
    // 构建螺纹
	BRepOffsetAPI_ThruSections aTool(Standard_True);
	aTool.AddWire(threadingWire1);
	aTool.AddWire(threadingWire2);
	aTool.CheckCompatibility(Standard_False);
	TopoDS_Shape myThreading = aTool.Shape();

2.4 合并模型

  最后我们使用TopoDS_Compound 和 BRep_Builder 类从 myBody和myThreading构建单个形状,完成瓶子的制作。

    // 整合模型
	TopoDS_Compound aRes;
	BRep_Builder aBuilder;
	aBuilder.MakeCompound(aRes);
	aBuilder.Add(aRes, myBody);
	aBuilder.Add(aRes, myThreading);

3 完整代码下载

  
完整建模平台源码下载

  

#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrimAPI_MakeCone.hxx>
#include <BRepPrimAPI_MakeTorus.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepOffsetAPI_MakePipe.hxx>  
#include <AIS_Shape.hxx>

#include <Geom_TrimmedCurve.hxx>
#include <GC_MakeArcOfCircle.hxx>
#include <GC_MakeSegment.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <TopoDS_Wire.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <TopoDS.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepFilletAPI_MakeFillet.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <Geom_Plane.hxx>
#include <TopoDS_Edge.hxx>
#include <BRepOffsetAPI_MakeThickSolid.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom2d_Ellipse.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <GCE2d_MakeSegment.hxx>
#include <BRepLib.hxx>
#include <BRepOffsetAPI_ThruSections.hxx>
#include <Geom_BezierCurve.hxx>


TopoDS_Shape CreateBottle(Standard_Real myWidth /*= 4.0*/, Standard_Real myHeight /*= 6.0*/, Standard_Real myThickness /*= 2.0*/)
{
	// 轮廓:定义支持点
	gp_Pnt aPnt1(-myWidth / 2., 0, 0);
	gp_Pnt aPnt2(-myWidth / 2., -myThickness / 4., 0);
	gp_Pnt aPnt3(0, -myThickness / 2., 0);
	gp_Pnt aPnt4(myWidth / 2., -myThickness / 4., 0);
	gp_Pnt aPnt5(myWidth / 2., 0, 0);
	// 轮廓:定义几何图形
	Handle(Geom_TrimmedCurve) anArcOfCircle = GC_MakeArcOfCircle(aPnt2, aPnt3, aPnt4);
	Handle(Geom_TrimmedCurve) aSegment1 = GC_MakeSegment(aPnt1, aPnt2);
	Handle(Geom_TrimmedCurve) aSegment2 = GC_MakeSegment(aPnt4, aPnt5);
	// 轮廓:定义拓扑结构
	TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aSegment1);
	TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(anArcOfCircle);
	TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(aSegment2);
	TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3);
	// 轮廓:完成轮廓
	gp_Ax1 xAxis = gp::OX();    // 获得X轴
	gp_Trsf aTrsf;
	aTrsf.SetMirror(xAxis);
	BRepBuilderAPI_Transform aBRepTrsf(aWire, aTrsf);
	TopoDS_Shape aMirroredShape = aBRepTrsf.Shape();
	TopoDS_Wire aMirroredWire = TopoDS::Wire(aMirroredShape);
	BRepBuilderAPI_MakeWire mkWire;
	mkWire.Add(aWire);
	mkWire.Add(aMirroredWire);
	TopoDS_Wire myWireProfile = mkWire.Wire();
	// 瓶身:拉伸轮廓
	TopoDS_Face myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile);
	gp_Vec aPrismVec(0, 0, myHeight);
	TopoDS_Shape myBody = BRepPrimAPI_MakePrism(myFaceProfile, aPrismVec);
	// 瓶身:倒角
	BRepFilletAPI_MakeFillet mkFillet(myBody);
	TopExp_Explorer anEdgeExplorer(myBody, TopAbs_EDGE);
	while (anEdgeExplorer.More()) 
	{
		TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExplorer.Current());
		//Add edge to fillet algorithm
		mkFillet.Add(myThickness / 12., anEdge);
		anEdgeExplorer.Next();
	}
	myBody = mkFillet.Shape();
	// 瓶身:添加瓶颈
	gp_Pnt neckLocation(0, 0, myHeight);
	gp_Dir neckAxis = gp::DZ();
	gp_Ax2 neckAx2(neckLocation, neckAxis);
	Standard_Real myNeckRadius = myThickness / 4.;
	Standard_Real myNeckHeight = myHeight / 10.;
	BRepPrimAPI_MakeCylinder MKCylinder(neckAx2, myNeckRadius, myNeckHeight);
	TopoDS_Shape myNeck = MKCylinder.Shape();
	myBody = BRepAlgoAPI_Fuse(myBody, myNeck);
	// 瓶身:创造中空的实体
	TopoDS_Face faceToRemove;
	Standard_Real zMax = -1;
	for (TopExp_Explorer aFaceExplorer(myBody, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next())
	{
		TopoDS_Face aFace = TopoDS::Face(aFaceExplorer.Current());
		// Check if <aFace> is the top face of the bottle's neck
		Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
		if (aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane)) 
		{
			Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface);
			gp_Pnt aPnt = aPlane->Location();
			Standard_Real aZ = aPnt.Z();
			if (aZ > zMax) {
				zMax = aZ;
				faceToRemove = aFace;
			}
		}
	}
	TopTools_ListOfShape facesToRemove;
	facesToRemove.Append(faceToRemove);
	BRepOffsetAPI_MakeThickSolid BodyMaker;
	BodyMaker.MakeThickSolidByJoin(myBody, facesToRemove, -myThickness / 50, 1.e-3);
	myBody = BodyMaker.Shape();

	// 螺纹:创建表面
	Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);
	Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);
	// 螺纹:定义二维曲线
	gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.);
	gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.);
	gp_Ax2d anAx2d(aPnt, aDir);
	Standard_Real aMajor = 2. * M_PI;
	Standard_Real aMinor = myNeckHeight / 10;
	Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);
	Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4);
	Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI);
	Handle(Geom2d_TrimmedCurve) anArc2 = new Geom2d_TrimmedCurve(anEllipse2, 0, M_PI);
	gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0);
	gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI);
	Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2);
	// 螺纹:创建边和线
	TopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1);
	TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1);
	TopoDS_Edge anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2);
	TopoDS_Edge anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment, aCyl2);
	TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1);
	TopoDS_Wire threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2, anEdge2OnSurf2);
	BRepLib::BuildCurves3d(threadingWire1);
	BRepLib::BuildCurves3d(threadingWire2);
	// 构建螺纹
	BRepOffsetAPI_ThruSections aTool(Standard_True);
	aTool.AddWire(threadingWire1);
	aTool.AddWire(threadingWire2);
	aTool.CheckCompatibility(Standard_False);
	TopoDS_Shape myThreading = aTool.Shape();
	// 整合模型
	TopoDS_Compound aRes;
	BRep_Builder aBuilder;
	aBuilder.MakeCompound(aRes);
	aBuilder.Add(aRes, myBody);
	aBuilder.Add(aRes, myThreading);

	return aRes;
}

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

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

相关文章

如何在Linux部署DataEase数据分析服务并实现无公网IP远程分析内网数据信息

文章目录 前言1. 安装DataEase2. 本地访问测试3. 安装 cpolar内网穿透软件4. 配置DataEase公网访问地址5. 公网远程访问Data Ease6. 固定Data Ease公网地址 前言 DataEase 是开源的数据可视化分析工具&#xff0c;帮助用户快速分析数据并洞察业务趋势&#xff0c;从而实现业务…

IBM:《2024年消费者调研:无处不在的人工智能彻底变革零售业》

1月17日&#xff0c;IBM商业价值研究院最近发布了第三份两年一度的消费者调研报告。 这项名为《无处不在的人工智能彻底改变零售业&#xff1a;客户不会等待》的报告&#xff0c;对包含中国在内的全球近20000名消费者进行了调研&#xff0c;相关结果反映了消费者对零售体验的普…

【Python】进阶学习:一文了解NotImplementedError的作用

【Python】进阶学习&#xff1a;一文了解NotImplementedError的作用 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望…

2020-11-08 字符串指定位置倒序输出

缘由https://bbs.csdn.net/topics/398165677 //字符串指定位置倒序输出缘由https://bbs.csdn.net/topics/398165677char aa[] "abcABCabc\n";int a 3, b 5, c 0, d b;while (aa[c] ! \n)if (c < a || c > b)cout << aa[c]; else if(d > a) cout …

目标检测——YOLOv4算法解读

论文&#xff1a;YOLOv4&#xff1a;Optimal Speed and Accuracy of Object Detection 作者&#xff1a;Alexey Bochkovskiy, Chien-Yao Wang, Hong-Yuan Mark Liao 链接&#xff1a;https://arxiv.org/pdf/2004.10934.pdf 代码&#xff1a;https://github.com/AlexeyAB/darkne…

弹性盒子布局 Flexbox Layout

可以嵌套下去 1.display 属性 默认行排列 <style>.flex-item{ height: 20px;width: 10px;background-color: #f1f1f1;margin: 10px;}</style> </head> <body> <div class"flex-container"><div class"flex-item">1&l…

如何实现固定公网地址远程SSH连接Linux Deepin系统

文章目录 前言1. 开启SSH服务2. Deppin安装Cpolar3. 配置ssh公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 前言 Deepin操作系统是一个基于Debian的Linux操作系统&#xff0c;专注于使用者对日常办公、学习、生活和娱乐的操作体验的极致&#xff0…

探索数据结构:双向链表的灵活优势

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 前言 前面我们学习了单链表&#xff0c;它解决了顺序表中插入删除需…

第110讲:Mycat实践指南:指定Hash算法分片下的水平分表详解

文章目录 1.应用指定Hash算法分片的概念2.使用应用指定Hash算法分片对某张表进行水平拆分2.1.在所有的分片节点中创建表结构2.2.配置Mycat实现应用指定Hash算法分片的水平分表2.2.1.配置Schema配置文件2.2.2.配置Rule分片规则配置文件2.2.3.配置Server配置文件2.2.4.重启Mycat …

什么牌子的蓝牙耳机质量好?2024年精选机型,真实体验分享

​对于新手来说&#xff0c;真无线蓝牙耳机的选购可能显得有些复杂。网络上有许多关于蓝牙耳机品牌、音质、舒适度的讨论。我整理了五款佩戴舒适且音质表现不错的真无线蓝牙耳机&#xff0c;希望能为你提供有价值的参考&#xff0c;不要错过哦&#xff01; 一、蓝牙耳机选购技巧…

训练YOLOv8m时AMP显示v8n

在训练Yolov8模型时&#xff0c;使用AMP&#xff08;Automatic Mixed Precision&#xff09;可以加速训练过程并减少显存的使用。AMP是一种混合精度训练技术&#xff0c;它通过将模型参数的计算转换为低精度&#xff08;如半精度&#xff09;来提高训练速度&#xff0c;同时保持…

es 分词器详解

基本概念 分词器官方称之为文本分析器&#xff0c;顾名思义&#xff0c;是对文本进行分析处理的一种手段&#xff0c;基本处理逻辑为按照预先制定的分词规则&#xff0c;把原始文档分割成若干更小粒度的词项&#xff0c;粒度大小取决于分词器规则。 分词器发生的时期 1、分词…

pytorch之诗词生成6--eval

先上代码&#xff1a; import tensorflow as tf from dataset import tokenizer import settings import utils# 加载训练好的模型 model tf.keras.models.load_model(r"E:\best_model.h5") # 随机生成一首诗 print(utils.generate_random_poetry(tokenizer, model)…

微信公众号测试号里面显示若依前端页面

内网穿透 注册购买内网穿透隧道 https://natapp.cn/ 启动成功 这样就绑定你的本地启动项目 微信公众测试号配置 注册微信公众号测试号 获取access_token&#xff0c;AppID与appsecret 调用微信官方接口生成access_token&#xff08;AppID和AppSecret可在“微信公众平台-设置…

C++ STL库的基本用法

目录 vector set queue priority_queue(堆)优先队列 大根堆 小根堆 map unordered_map vector vector<int> heap;//一维数组 for(int i1;i<10;i){heap.push_back(i); } heap.push_back();//元素插入尾部 heap.pop_back();//弹出尾部元素 heap.empty();// 判…

StarRocks——滴滴的极速多维分析实践

背景 滴滴集团作为生活服务领域的头部企业&#xff0c;其中橙心优选经过一年多的数据体系建设&#xff0c;逐渐将一部分需要实时交互查询&#xff0c;即席查询的多维数据分析需求由ClickHouse迁移到了StarRocks中&#xff0c;接下来以StarRocks实现的漏斗分析为例介绍StarRocks…

kafka 管理工具 Offset Explorer 使用

一、连接 二、查询数据 三、插入测试数据

突飞猛进,智能饮品机器人如何助力实体经济?

近日&#xff0c;财务部公布了2024年第一季度及全年财报。数据显示&#xff0c;连锁品牌增长速度惊人&#xff0c;这其中不得不提到智能饮品机器人的使用&#xff0c;为不同的品牌门店拼速度、抢点位立下了不小的功劳&#xff0c;那么智能饮品机器人到底如何助力各门店&#xf…

工作中Git如何切换远程仓库地址

工作中Git如何切换远程仓库地址 部门之前的仓库不用了&#xff0c;重新建了一个仓库&#xff0c;但是上传代码还是上传到了之前的仓库里面了&#xff0c;所以得进行修改&#xff0c;下面将修改地址的方法进行操作。 方法一、直接修改远程仓库地址 查看当前远程仓库地址 git …

LLM - 大语言模型(LLM) 概述

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/136617643 大语言模型(LLM, Large Language Model)的发展和应用是一个非常广泛的领域&#xff0c;涉及从早期的统计模型到现代基于深度学…