当前位置: 首页 > news >正文

Qt扩展-QCustomPlot绘图基础概述

QCustomPlot绘图基础概述

  • 一、概述
  • 二、改变外观
    • 1. Graph 类型
    • 2. Axis 坐标轴
    • 3. 网格
  • 三、案例
    • 1. 简单布局两个图
    • 2. 绘图与多个轴和更先进的样式
    • 3. 绘制日期和时间数据
  • 四、其他Graph:曲线,条形图,统计框图,…

一、概述

本教程使用 customPlot 作为指向 QCustomPlot 实例的指针。如果我们在QtCreator中提升了一个控件,那么我们可能会通过ui->customPlot(或我们给控件的任何名称)来访问相应的控件。

我们可以通过customPlot->addGraph()在绘图中创建一个新Graph。然后你给Graph分配一些数据点,例如通过customPlot->graph(0)->setData(…),例如以两个QVector的形式表示x和y(键和值)。

QCustomPlot使用术语键和值而不是x和y的原因是为了更灵活地分配哪个轴具有什么角色。因此,如果你将左轴定义为“关键轴”,将下轴定义为“价值轴”,你就可以在图表的左侧绘制出一个直立的图表。

默认情况下,QCustomPlot控件有四个轴:类型为QCPAxis的customPlot->xAxis、yAxis、xAxis2和yAxis2,分别对应于下、左、上和右轴。它们的范围定义了绘图的哪一部分是当前可见的:customPlot->xAxis->setRange(- 1,1)。

要对屏幕上显示的绘图进行任何类型的更改,请调用customPlot->replot(),相当于手动刷新,和QPainter里面的 refresh() 一样。请注意,当控件调整大小和触发内置用户交互时,将自动进行重新绘制。例如,这样的用户交互是用鼠标拖动轴范围和用鼠标滚轮缩放。

// 生成数据:
QVector<double> x(101), y(101); // initialize with entries 0..100
for (int i=0; i<101; ++i)
{x[i] = i/50.0 - 1; // x goes from -1 to 1y[i] = x[i]*x[i]; // let's plot a quadratic function
}// create graph and assign data to it:
customPlot->addGraph();
customPlot->graph(0)->setData(x, y);// give the axes some labels:
customPlot->xAxis->setLabel("x");
customPlot->yAxis->setLabel("y");// set axes ranges, so we see all data:
customPlot->xAxis->setRange(-1, 1);
customPlot->yAxis->setRange(0, 1);
customPlot->replot();

输出应该如下所示。

在这里插入图片描述

标记刻度和标记是由轴当前使用的轴自动选择的。这个轴这是QCPAxisTicker类型的实例,可以通过xAxis->ticker()等方式访问。

我们可以通过 xAxis->ticker()->setTickCount(6) 来调整自动尝试创建的大致刻度数。默认的轴刻度非常适合简单的数字显示,但是也有专门的类,例如时间刻度、日历日期刻度、类别刻度、圆周率(或其他符号单位)和对数轴。有关详细信息,请参阅QCPAxisTicker文档。

轴的刻度标签(数字)永远不会超出控件边框,即使它们变宽了,因为这个控件会自动去计算轴刻度,而且这是在默认情况下打开。如果刻度标签和轴标签需要更多的空间,它会使轴矩形收缩。如果我们不希望自动确定边距,请通过调用customPlot->axisRect()->setAutoMargins(QCP::msNone)来禁用该行为。我们也可以通过customPlot->axisRect()-> setmargin(…)手动调整边距。

二、改变外观

1. Graph 类型

Graph的外观由许多因素决定,所有这些因素都可以修改。以下是最重要的几点:

  • 线条样式:调用graph->setLineStyle(…)。对于所有可能的线条样式,请参阅QCPGraph::LineStyle文档或介绍页面上的线条样式演示截图。
    在这里插入图片描述
枚举器类型含义
lsNone数据点不与任何直线相连(例如,数据仅根据散点样式用符号表示)
lsLine数据点由一条直线连接
lsStepLeft线绘制为步长,其中步长高度是左侧数据点的值
lsStepRight线被绘制为步,其中步高是正确数据点的值
lsStepCenter当步长位于两个数据点之间时,线被绘制为步长
lsImpulse每个数据点用一条平行于值轴的线表示,这条线从数据点延伸到零值线
  • 线条 Pen:QPainter框架提供的所有笔都是可用的,例如实线、虚线、虚线、不同宽度、颜色、透明度等。通过graph->setPen(…)设置配置的笔刷的。
  • 散点符号:调用graph->setScatterStyle(…)来改变散点符号的外观。对于所有可能的分散样式,请参阅QCPScatterStyle文档或介绍页面上显示的分散样式演示截图。如果我们不希望在数据点上显示任何散点符号,请将图的散点样式设置为QCPScatterStyle::ssNone。
枚举类型外观含义
ssNone没有绘制散点符号(例如在QCPGraph中,数据仅用线条表示)
ssDot单个像素(如果你想要一个具有一定半径的圆形,可以使用ssDisc或scircle)
ssCross在这里插入图片描述一个十字架
ssPlus在这里插入图片描述一个+
ssCirclessCircle.png一个圆
ssDiscssDisc.png一个用钢笔的颜色填充的圆圈(不像scircle那样用画笔填充)
ssSquaressSquare.png一个正方形
ssDiamondssDiamond.png一颗钻石
ssStarssStar.png有八臂的星形,即十字和正号的组合
ssTrianglessTriangle.png立在基线上的等边三角形
ssTriangleInvertedssTriangleInverted.png一个等边三角形,立在角上
ssCrossSquaressCrossSquare.png有一个十字的正方形
ssPlusSquaressPlusSquare.png里面有加号的正方形
ssCrossCirclessCrossCircle.png一个里面有十字架的圆
ssPlusCirclessPlusCircle.png里面有加号的圆圈
ssPeacessPeace.png一个圆,有一条垂直线和两条向下的对角线
ssPixmap由setPixmap指定的自定义像素图,以数据点坐标为中心
ssCustom每个散射执行自定义绘制操作(如QPainterPath,参见setCustomPath)
  • Graph下或两个Graph之间的填充:QPainter框架提供的所有笔刷都可以用于Graph填充:实体,各种图案,纹理,渐变,颜色,透明度等。通过graph->setBrush(…)设置已配置的画笔。

2. Axis 坐标轴

我们可以可以通过更改绘制轴的笔和标签使用的字体来修改轴的外观。看一下QCPAxis的文档应该是不言自明的。这里有一个最重要的属性的快速总结:

  • setBasePen,
  • setTickPen,
  • setTickLength,
  • setSubTickLength,
  • setSubTickPen,
  • setTickLabelFont,
  • setLabelFont,
  • setTickLabelPadding,
  • setLabelPadding。

你可以用setRangeReversed反转一个轴(例如,让值从左到右减少而不是增加)。

如果你想在轴端装饰(如箭头),使用setLowerEnding或setUpperEnding。

3. 网格

我们可以通过访问轴的相应QCPGrid实例来修改网格。

例如,通过访问customPlot->yAxis->grid()来更改绑定到左轴的水平网格线的外观。网格线的外观基本上是绘制它们的QPen,可以通过yAxis->grid()->setPen()设置。点0处的网格线可以用不同的笔绘制,它可以配置setZeroLinePen。如果我们不希望用特殊的笔绘制零线,只需将其设置为Qt::NoPen,那么标记0处的网格线将使用普通网格笔绘制。
子网格线默认设置为不可见。它们可以通过grid()->setSubGridVisible(true)激活。

三、案例

1. 简单布局两个图

这里有一个例子,它创建了衰减余弦函数及其指数包络的图像:

在这里插入图片描述

// 添加两个图并设置外观:
customPlot->addGraph();
customPlot->graph(0)->setPen(QPen(Qt::blue)); // 第一张图的线条颜色为蓝色
customPlot->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); //第一个Graph将被半透明的蓝色填充
customPlot->addGraph();
customPlot->graph(1)->setPen(QPen(Qt::red)); // 第二张图的线条颜色为红色// 生成一些数据点(第一张图为y0,第二张图为y1):
QVector<double> x(251), y0(251), y1(251);
for (int i=0; i<251; ++i)
{x[i] = i;y0[i] = qExp(-i/150.0)*qCos(i/10.0); // 指数衰减余弦y1[i] = qExp(-i/150.0);              // 指数函数
}// configure right and top axis to show ticks but no labels:
// (see QCPAxisRect::setupFullAxesBox for a quicker method to do this)
customPlot->xAxis2->setVisible(true);
customPlot->xAxis2->setTickLabels(false);
customPlot->yAxis2->setVisible(true);
customPlot->yAxis2->setTickLabels(false);// make left and bottom axes always transfer their ranges to right and top axes:
connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange)));
connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange)));// pass data points to graphs:
customPlot->graph(0)->setData(x, y0);
customPlot->graph(1)->setData(x, y1);// let the ranges scale themselves so graph 0 fits perfectly in the visible area:
customPlot->graph(0)->rescaleAxes();// same thing for graph 1, but only enlarge ranges (in case graph 1 is smaller than graph 0):
customPlot->graph(1)->rescaleAxes(true);// Note: we could have also just called customPlot->rescaleAxes(); instead
// Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);

正如你所看到的,对 Graph 应用填充就像设置一个不是 Qt::NoBrush的笔刷一样简单。填充将从Graph(这里是Graph0)到平行于键(这里是x)轴的零值线。如果我们想在这个图和另一个图之间填充通道,我们将额外调用graph->setChannelFillGraph(otherGraph)。要删除通道填充,只需将0作为otherGraph 传递即可,填充将像以前一样一直到达零值线。要完全移除填充,调用graph->setBrush(Qt::NoBrush)。

2. 绘图与多个轴和更先进的样式

现在,让我们来看一个更复杂的示例,创建演示截图,其中包含四个轴上的五个Graph,纹理填充,垂直误差条,图例,作为小数分隔符的点等。

112

customPlot->setLocale(QLocale(QLocale::English, QLocale::UnitedKingdom)); // period as decimal separator and comma as thousand separator
customPlot->legend->setVisible(true);
QFont legendFont = font();  // start out with MainWindow's font..
legendFont.setPointSize(9); // and make a bit smaller for legend
customPlot->legend->setFont(legendFont);
customPlot->legend->setBrush(QBrush(QColor(255,255,255,230)));
// by default, the legend is in the inset layout of the main axis rect. So this is how we access it to change legend placement:
customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignBottom|Qt::AlignRight);// setup for graph 0: key axis left, value axis bottom
// will contain left maxwell-like function
customPlot->addGraph(customPlot->yAxis, customPlot->xAxis);
customPlot->graph(0)->setPen(QPen(QColor(255, 100, 0)));
customPlot->graph(0)->setBrush(QBrush(QPixmap("./balboa.jpg"))); // fill with texture of specified image
customPlot->graph(0)->setLineStyle(QCPGraph::lsLine);
customPlot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 5));
customPlot->graph(0)->setName("Left maxwell function");// setup for graph 1: key axis bottom, value axis left (those are the default axes)
// will contain bottom maxwell-like function with error bars
customPlot->addGraph();
customPlot->graph(1)->setPen(QPen(Qt::red));
customPlot->graph(1)->setBrush(QBrush(QPixmap("./balboa.jpg"))); // same fill as we used for graph 0
customPlot->graph(1)->setLineStyle(QCPGraph::lsStepCenter);
customPlot->graph(1)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, Qt::red, Qt::white, 7));
customPlot->graph(1)->setName("Bottom maxwell function");
QCPErrorBars *errorBars = new QCPErrorBars(customPlot->xAxis, customPlot->yAxis);
errorBars->removeFromLegend();
errorBars->setDataPlottable(customPlot->graph(1));// setup for graph 2: key axis top, value axis right
// will contain high frequency sine with low frequency beating:
customPlot->addGraph(customPlot->xAxis2, customPlot->yAxis2);
customPlot->graph(2)->setPen(QPen(Qt::blue));
customPlot->graph(2)->setName("High frequency sine");// setup for graph 3: same axes as graph 2
// will contain low frequency beating envelope of graph 2
customPlot->addGraph(customPlot->xAxis2, customPlot->yAxis2);
QPen blueDotPen;
blueDotPen.setColor(QColor(30, 40, 255, 150));
blueDotPen.setStyle(Qt::DotLine);
blueDotPen.setWidthF(4);
customPlot->graph(3)->setPen(blueDotPen);
customPlot->graph(3)->setName("Sine envelope");// setup for graph 4: key axis right, value axis top
// will contain parabolically distributed data points with some random perturbance
customPlot->addGraph(customPlot->yAxis2, customPlot->xAxis2);
customPlot->graph(4)->setPen(QColor(50, 50, 50, 255));
customPlot->graph(4)->setLineStyle(QCPGraph::lsNone);
customPlot->graph(4)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 4));
customPlot->graph(4)->setName("Some random data around\na quadratic function");// generate data, just playing with numbers, not much to learn here:
QVector<double> x0(25), y0(25);
QVector<double> x1(15), y1(15), y1err(15);
QVector<double> x2(250), y2(250);
QVector<double> x3(250), y3(250);
QVector<double> x4(250), y4(250);
for (int i=0; i<25; ++i) // data for graph 0
{x0[i] = 3*i/25.0;y0[i] = qExp(-x0[i]*x0[i]*0.8)*(x0[i]*x0[i]+x0[i]);
}
for (int i=0; i<15; ++i) // data for graph 1
{x1[i] = 3*i/15.0;;y1[i] = qExp(-x1[i]*x1[i])*(x1[i]*x1[i])*2.6;y1err[i] = y1[i]*0.25;
}
for (int i=0; i<250; ++i) // data for graphs 2, 3 and 4
{x2[i] = i/250.0*3*M_PI;x3[i] = x2[i];x4[i] = i/250.0*100-50;y2[i] = qSin(x2[i]*12)*qCos(x2[i])*10;y3[i] = qCos(x3[i])*10;y4[i] = 0.01*x4[i]*x4[i] + 1.5*(rand()/(double)RAND_MAX-0.5) + 1.5*M_PI;
}// pass data points to graphs:
customPlot->graph(0)->setData(x0, y0);
customPlot->graph(1)->setData(x1, y1);
errorBars->setData(y1err);
customPlot->graph(2)->setData(x2, y2);
customPlot->graph(3)->setData(x3, y3);
customPlot->graph(4)->setData(x4, y4);
// activate top and right axes, which are invisible by default:
customPlot->xAxis2->setVisible(true);
customPlot->yAxis2->setVisible(true);
// set ranges appropriate to show data:
customPlot->xAxis->setRange(0, 2.7);
customPlot->yAxis->setRange(0, 2.6);
customPlot->xAxis2->setRange(0, 3.0*M_PI);
customPlot->yAxis2->setRange(-70, 35);
// set pi ticks on top axis:
customPlot->xAxis2->setTicker(QSharedPointer<QCPAxisTickerPi>(new QCPAxisTickerPi));
// add title layout element:
customPlot->plotLayout()->insertRow(0);
customPlot->plotLayout()->addElement(0, 0, new QCPTextElement(customPlot, "Way too many graphs in one plot", QFont("sans", 12, QFont::Bold)));
// set labels:
customPlot->xAxis->setLabel("Bottom axis with outward ticks");
customPlot->yAxis->setLabel("Left axis label");
customPlot->xAxis2->setLabel("Top axis label");
customPlot->yAxis2->setLabel("Right axis label");
// make ticks on bottom axis go outward:
customPlot->xAxis->setTickLength(0, 5);
customPlot->xAxis->setSubTickLength(0, 3);
// make ticks on right axis go inward and outward:
customPlot->yAxis2->setTickLength(3, 3);
customPlot->yAxis2->setSubTickLength(1, 1);

正如我们所看到的,我们可以自由定义哪个轴应该在Graph中扮演哪个角色。例如,索引为0的Graph使用左轴(yAxis)作为其键,底部轴(xAxis)作为其值。因此,Graph相对于左轴是向上的:

为了显示Graph1的错误条,我们创建了一个QCPErrorBars实例,它可以附加到其他绘图表(如QCPGraph)并为它们提供错误条。有关所使用方法的进一步说明,请查看相应的文档。

3. 绘制日期和时间数据

接下来,我们将了解如何绘制日期和/或时间相关数据。它基本上归结为在各自的轴上安装QCPAxisTickerDateTime类型的不同轴刻度。

在这里插入图片描述

// set locale to english, so we get english month names:
customPlot->setLocale(QLocale(QLocale::English, QLocale::UnitedKingdom));// seconds of current time, we'll use it as starting point in time for data:
double now = QDateTime::currentDateTime().toTime_t();
srand(8); // set the random seed, so we always get the same random data// create multiple graphs:
for (int gi=0; gi<5; ++gi)
{customPlot->addGraph();QColor color(20+200/4.0*gi,70*(1.6-gi/4.0), 150, 150);customPlot->graph()->setLineStyle(QCPGraph::lsLine);customPlot->graph()->setPen(QPen(color.lighter(200)));customPlot->graph()->setBrush(QBrush(color));// generate random walk data:QVector<QCPGraphData> timeData(250);for (int i=0; i<250; ++i){timeData[i].key = now + 24*3600*i;if (i == 0)timeData[i].value = (i/50.0+1)*(rand()/(double)RAND_MAX-0.5);elsetimeData[i].value = qFabs(timeData[i-1].value)*(1+0.02/4.0*(4-gi)) + (i/50.0+1)*(rand()/(double)RAND_MAX-0.5);}customPlot->graph()->data()->set(timeData);
}// configure bottom axis to show date instead of number:
QSharedPointer<QCPAxisTickerDateTime> dateTicker(new QCPAxisTickerDateTime);
dateTicker->setDateTimeFormat("d. MMMM\nyyyy");
customPlot->xAxis->setTicker(dateTicker);// configure left axis text labels:
QSharedPointer<QCPAxisTickerText> textTicker(new QCPAxisTickerText);
textTicker->addTick(10, "a bit\nlow");
textTicker->addTick(50, "quite\nhigh");
customPlot->yAxis->setTicker(textTicker);// set a more compact font size for bottom and left axis tick labels:
customPlot->xAxis->setTickLabelFont(QFont(QFont().family(), 8));
customPlot->yAxis->setTickLabelFont(QFont(QFont().family(), 8));// set axis labels:
customPlot->xAxis->setLabel("Date");
customPlot->yAxis->setLabel("Random wobbly lines value");// make top and right axes visible but without ticks and labels:
customPlot->xAxis2->setVisible(true);
customPlot->yAxis2->setVisible(true);
customPlot->xAxis2->setTicks(false);
customPlot->yAxis2->setTicks(false);
customPlot->xAxis2->setTickLabels(false);
customPlot->yAxis2->setTickLabels(false);// set axis ranges to show all data:
customPlot->xAxis->setRange(now, now+24*3600*249);
customPlot->yAxis->setRange(0, 60);// show legend with slightly transparent background brush:
customPlot->legend->setVisible(true);
customPlot->legend->setBrush(QColor(255, 255, 255, 150));

传递给 dateTicker->setDateTimeFormat() 的字符串与传递给 QDateTime::toString 的字符串具有相同的日期格式化选项,请参阅Qt文档。QCustomPlot中的所有日期/时间坐标都被处理为自午夜1以来的秒数。1970年1月,UTC(被称为Unix/Epoch Time)。这也是我们在Qt日期/时间类上调用QDateTime::toTime_t或setTime_t时使用的单元。

对于亚秒级精度,轴计时器与浮点数一起工作。因此,小于1.0的值表示相应的几分之一秒。我们可以使用QCPAxisTickerDateTime::dateTimeToKey和keyToDateTime来转换浮点Unix时间和QDateTime,独立于Qt版本(Qt的QDateTime::toMSecsSinceEpoch仅在Qt 4.7中引入)。

四、其他Graph:曲线,条形图,统计框图,…

到目前为止,我们只看了图表。由于它们是如此主要的用例,QCustomPlot为它们提供了一个专门的接口。我们一直在使用它:QCustomPlot::addGraph, QCustomPlot::graph等。但这并不是故事的全部。QCustomPlot有一个更通用的接口,用于在图中绘制数据的类,称为Plottables。

这个接口是围绕抽象基类QCPAbstractPlottable构建的。所有Plottables都来自这个类,还有我们熟悉的QCPGraph类。QCustomPlot提供了许多其他绘图类:

  • QCPGraph:这是我们一直在使用的可绘图类。将一系列数据点显示为具有不同线条样式、填充和散点的Graph。

  • QCPCurve:类似于QCPGraph,不同之处在于它用于显示参数曲线。与函数图不同,它们可能有循环。

  • QCPBars:一个条形图。取一系列数据点并用条形表示它们。如果绘图中有多个qcpbar绘图,则可以将它们堆叠在一起,如介绍页面上的截图所示。

  • QCPStatisticalBox:统计箱图。取一个五位数汇总(最小值、下四分位数、中位数、上四分位数、最大值),并将其表示为统计框。也可以显示异常值。

  • QCPColorMap:一个2D地图,通过使用颜色渐变来可视化第三个数据维度。类QCPColorScale伴随着这个图表来可视化图表中的数据比例。

  • QCPFinancial:一个图表,可以使用烛台或OHLC条来可视化例如股票价格开盘,高点,低点,收盘信息。

  • QCPErrorBars:这是一个特殊的图表,因为它附加到第二个图表上,以允许在其他图表的数据点上显示错误栏。

与QCPGraph不同的是,其他绘图需要在QCustomPlot之外使用new创建。这意味着没有addCurve或addBars函数,而有addGraph函数。

可绘图表所属的QCustomPlot实例是从可绘图表的构造函数中传递的轴中推断出来的。然后QCustomPlot获得可绘图表的所有权。可以使用QCustomPlot::plottable(int index)访问现有的plottables,并且可以使用QCustomPlot::plottableCount检索图(包括Graph)中的plottables总数。当然我们可以自己设置一个Map去维护这个索引关系的。

下面是一个创建三个柱状图的快速示例:

QCPBars *myBars = new QCPBars(customPlot->xAxis, customPlot->yAxis);
// now we can modify properties of myBars:
myBars->setName("Bars Series 1");
QVector<double> keyData;
QVector<double> valueData;
keyData << 1 << 2 << 3;
valueData << 2 << 4 << 8;
myBars->setData(keyData, valueData);
customPlot->rescaleAxes();
customPlot->replot();

可以在示例项目和其他教程中找到有关其他绘图的更多详细信息。此外,每种可绘图类型在各自类的文档页面上都有详细的描述。

当然,完全有可能编写我们自己的图表,使任何数据看起来完全符合我们的需要。我们应该查看QCPAbstractPlottable文档,了解如何开始创建它的子类。我们还可以查看现有的标绘图,了解它们是如何工作的。

为此,建议首先查看QCPBars或QCPCurve。QCPGraph功能非常丰富,因此可能不太适合作为入门起点。

相关文章:

Qt扩展-QCustomPlot绘图基础概述

QCustomPlot绘图基础概述 一、概述二、改变外观1. Graph 类型2. Axis 坐标轴3. 网格 三、案例1. 简单布局两个图2. 绘图与多个轴和更先进的样式3. 绘制日期和时间数据 四、其他Graph&#xff1a;曲线&#xff0c;条形图&#xff0c;统计框图&#xff0c;… 一、概述 本教程使用…...

二、局域网联机

目录 1.下载资源包 2.配置NetworkManager 3.编写测试UI 1.下载资源包 2.配置NetworkManager &#xff08;1&#xff09;在Assets/Prefabs下创建Network Prefabs List 相应设置如下&#xff1a; &#xff08;2&#xff09; 创建空物体“NetworkManager”并挂载NetworkMan…...

决策树剪枝:解决模型过拟合【决策树、机器学习】

如何通过剪枝解决决策树的过拟合问题 决策树是一种强大的机器学习算法&#xff0c;用于解决分类和回归问题。决策树模型通过树状结构的决策规则来进行预测&#xff0c;但在构建决策树时&#xff0c;常常会出现过拟合的问题&#xff0c;即模型在训练数据上表现出色&#xff0c;…...

Ubuntu部署运行ORB-SLAM2

ORB-SLAM2是特征点法的视觉SLAM集大成者&#xff0c;不夸张地说是必学代码。博主已经多次部署运行与ORB-SLAM2相关的代码&#xff0c;所以对环境和依赖很熟悉&#xff0c;对整个系统也是学习了几个月&#xff0c;一行行代码理解。本次在工控机上部署记录下完整的流程。 ORB-SLA…...

二十,镜面IBL--打印BRDF积分贴图

比起以往&#xff0c;这节应该是最轻松的了&#xff0c; 运行结果如下 代码如下&#xff1a; #include <osg/TextureCubeMap> #include <osg/TexGen> #include <osg/TexEnvCombine> #include <osgUtil/ReflectionMapGenerator> #include <osgDB/Re…...

自动驾驶:未来的道路上的挑战与机遇

自动驾驶&#xff1a;未来的道路上的挑战与机遇 文章目录 引言安全与道路事故的减少交通拥堵的缓解城市规划的变革技术和法律挑战结语 2023星火培训【专项营】Apollo开发者社区布道师倾力打造&#xff0c;包含PnC、新感知等的全新专项课程上线了。理论与实践相结合&#xff0c;…...

Go 语言 iota 的神奇力量

前言 当你深入研究官网库、开源库或者任何一个 Go 项目时&#xff0c;你都会发现 iota 这个神奇的标识符无处不在。它扮演着一种重要的角色&#xff0c;让代码变得更加简洁、清晰&#xff0c;并提高了可读性和可维护性。它的应用范围广泛&#xff0c;从枚举类型到位运算&#…...

前端开发和后端开发的一些建议

前端开发和后端开发是Web开发的两个方向 前端开发主要负责实现用户在浏览器上看到的界面和交互体验&#xff0c;包括HTML、CSS和JavaScript等技术。后端开发主要负责处理服务器端的逻辑和数据&#xff0c;包括数据库操作、服务器配置和接口开发等技术。 前端开发 前端开发需…...

基于 SpringBoot+Vue 的教室人事档案管理系统

1 简介 教师人事档案管理系统利用信息的合理管理&#xff0c;动态的、高效的、安全的实现了教师的各种需求&#xff0c;改变了传统的网上查看方式&#xff0c;使教师可以足不出户的在线查看最适合自己个人档案、奖惩信息、档案变动、培训报名或者新闻资讯。 1、教师后台功能模…...

Lua学习笔记:require非.lua拓展名的文件

前言 本篇在讲什么 Lua的require相关的内容 本篇需要什么 对Lua语法有简单认知 对C语法有简单认知 依赖Visual Studio工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠…...

Python 编程基础 | 第三章-数据类型 | 3.3、浮点数

一、浮点数...

beego---ORM相关操作

Beego框架是go语言开发的web框架。 **那什么是框架呢&#xff1f;**就是别人写好的代码&#xff0c;我们可以直接使用&#xff01;这个代码是专门针对某一个开发方向定制的&#xff0c;例如&#xff1a;我们要做一个网站&#xff0c;利用 beego 框架就能非常快的完成网站的开发…...

【网络原理】初始网络,了解概念

文章目录 1. 网络通信1.1 局域网LAN1.2 广域网WAN 2. 基础概念2.1 IP2.2 端口号 3. 认识协议4. 五元组5. 协议分层5.1 分层的作用5.2 OSI七层模型5.3 TCP/IP五层&#xff08;四层&#xff09;模型 6. 封装和分用 1. 网络通信 计算机与计算机之间是互相独立&#xff0c;是独立模…...

对象存储,从单机到分布式的演进

关于数据存储的相关知识,请大家关注“数据存储张”,各大平台同名。 通过《什么是云存储?从对象存储说起》我们对对象存储的历史、概念和基本使用有了一个大概的认识。而且我们以Minio为例,通过单机部署的模式实际操作了一下对象存储的GUI,感受了一下对象存储的用法。 在上…...

结构型设计模式——桥接模式

摘要 桥接模式(Bridge pattern): 使用桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。 一、桥接模式的意图 将抽象与实现分离开来&#xff0c;使它们可以独立变化。 二、桥接模式的类图 Abstraction: 定义抽象类的接口Implementor: 定义实现类接口 …...

keepalived的vip实现nginx节点的主备

nginx wget http://nginx.org/download/nginx-1.18.0.tar.gz tar zxvf nginx-1.18.0.tar.gzyum install -y gcc gcc-c pcre pcre-devel zlib zlib-devel openssl openssl-devel libnl3-develcd nginx-1.18.0 mkdir -p /usr/local/nginx #需要使用https&#xff0c;在编译时启用…...

C++之std::atomic解决多线程7个问题(二百四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…...

tailwindcss 如何在 uniapp 中使用

直接使用https://tailwindcss.com/docs/guides/vite这篇官方教程的写法是跑不通的&#xff0c;摸索以后整理了一下&#xff0c;最关键的是第6步 npm install -D tailwindcss postcss autoprefixernpx tailwindcss init -p在 tailwind.config.js 中写入 export default {conten…...

oracle-使用PLSQL工具自行修改用户密码

1、使用PLSQL工具&#xff0c;输入用户名和原密码登录&#xff0c;如下图 2、登录后&#xff0c;在会话下拉菜单中找到”Change password..” 3、在跳出的窗口中配置新密码&#xff0c;修改完成后单击”确认”&#xff0c;后退出PLSQL 4、重新打开PLSQL&#xff0c;使用新密码登…...

自动驾驶技术:现状与未来

自动驾驶技术&#xff1a;现状与未来 文章目录 引言自动驾驶技术的现状自动驾驶技术的挑战自动驾驶技术的未来结论结论 2023星火培训【专项营】Apollo开发者社区布道师倾力打造&#xff0c;包含PnC、新感知等的全新专项课程上线了。理论与实践相结合&#xff0c;全新的PnC培训不…...

C++ 类构造函数 析构函数

类的构造函数 类的构造函数是类的一种特殊的成员函数&#xff0c;它会在每次创建类的新对象时执行。 构造函数的名称与类的名称是完全相同的&#xff0c;并且不会返回任何类型&#xff0c;也不会返回 void。构造函数可用于为某些成员变量设置初始值。 下面的实例有助于更好地…...

C++标准模板(STL)- 输入/输出操纵符-(std::get_time,std::put_time)

操纵符是令代码能以 operator<< 或 operator>> 控制输入/输出流的帮助函数。 不以参数调用的操纵符&#xff08;例如 std::cout << std::boolalpha; 或 std::cin >> std::hex; &#xff09;实现为接受到流的引用为其唯一参数的函数。 basic_ostream::…...

蓝桥等考Python组别九级004

第一部分:选择题 1、Python L9 (15分) 运行下面程序,可以输出几行“*”?( ) for i in range(3): for j in range(4): print(*, end = ) print() 2345正确答案:B 2、Python L9...

gitee 远程仓库操作基础(二)

(1&#xff09;clone远端仓库,本地建立分支推送 (基于远程仓库版本库 本地建立分支开发新功能) git clone gitgitee.com:xxxxx/alsa_test.git git remote add origin gitgitee.com:xxxxx/alsa_test.git进入clone过后路径代码,查看本地分支,发现该项目远程仓库有很多分支 基于…...

Scala第四章节

Scala第四章节 scala总目录 章节目标 掌握分支结构的格式和用法掌握for循环和while循环的格式和用法掌握控制跳转语句的用法掌握循环案例理解do.while循环的格式和用法 1. 流程控制结构 1.1 概述 在实际开发中, 我们要编写成千上万行代码, 代码的顺序不同, 执行结果肯定也…...

【C++入门指南】类和对象(上)

【C杂货店】类和对象&#xff08;上&#xff09; 一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装4.1 访问限定符4.2 封装 五、类的作用域六、类的实例化七、类对象模型7.1 类对象的存储规则7.2 例题7.3结构体内存对齐规则 八、this指针8.2 t…...

web:[极客大挑战 2019]PHP

题目 点进页面显示如下 根据页面提示&#xff0c;这个网站有备份文件&#xff0c;备份文件一般是bak文件格式&#xff0c;用dirsearch扫描 访问之后下载了一个文件 里面都是一些代码 在index.php中发现了一个类的文件&#xff0c;一个get传参&#xff0c;然后将传进的值进行反序…...

Firefox 开发团队对 Vue 3 进行优化效果显著

Mozilla 官方博客近日发表文章《Faster Vue.js Execution in Firefox》&#xff0c;介绍了 Firefox 开发团队对 Vue 3 进行的优化。 文章写道&#xff0c;在使用 Speedometer 3 对 Firefox 进行基准测试时&#xff0c;他们发现 Vue.js test 的测试结果从 Vue 2 升级到 Vue 3 后…...

【Verilog 教程】6.5 Verilog避免Latch

关键词&#xff1a;触发器&#xff0c;锁存器 Latch 的含义 锁存器&#xff08;Latch&#xff09;&#xff0c;是电平触发的存储单元&#xff0c;数据存储的动作取决于输入时钟&#xff08;或者使能&#xff09;信号的电平值。仅当锁存器处于使能状态时&#xff0c;输出才会随着…...

怒刷LeetCode的第21天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;哈希表 方法二&#xff1a;计数器数组 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;分治法 方法二&#xff1a;快速幂 迭代 方法三&#xff1a;快速幂 递归 第三题 题目来源 题目内容 …...

160 作者 网站建设/seo综合查询站长工具关键词

五年级信息技术考试试题一、填空题。(每空3分共&#xff0c;21分)1、电子邮件是用Internet 进行的最普遍形式&#xff0c;它的英文名叫_____ 。2、_____是接收被删除的文件和文件夹。3、在电子邮箱中&#xff0c; _____是来信聚集地。4、幻灯片的目录区显示的是演示文稿的幻灯片…...

免费学做淘宝的网站/网络平台运营是做什么的

java中public与private还有protect的区别 总是忘记。...

广州城乡建设网站/昆明seo技术培训

当地时间3月19日&#xff0c;IBM Qiskit正式发布了Qiskit Metal[1]&#xff0c;一款用于超导量子计算机的开源电子设计自动化&#xff08;EDA&#xff09;软件。官方表示很期待看到Qiskit Metal在这个领域即将产生的影响&#xff0c;毕竟&#xff0c;IBM Qiskit已经从早期体验者…...

杭州网站建设方案服务公司/移动端seo关键词优化

在开始&#xff0c;我们先来看看这幅漫画的全貌&#xff01; 这幅漫画是以一个房子的侧方刨面图来绘画的。使用这样的一个房子来代表 Linux 内核。 地基 作为一个房子&#xff0c;最重要的莫过于其地基&#xff0c;在这个图片里&#xff0c;我们也从最下面的地基开始看起&…...

会做网站的公司/2345网址导航智能主板

工具 window10 django2.2.2 mysql5.6 django默认使用mysqlclient连接mysql&#xff0c;但是在window下直接安装mysqlclient不容易成功&#xff0c;可以使用pymysql 代替。 但使用如下方式报错&#xff1a; #settings.py import pymysql pymysql.intall_as_MySQLdb()django 3.…...

微信公众号怎么创建内容/什么是优化师

Q&#xff1a;Mongodb数据服务有什么用&#xff1f; A&#xff1a;首先&#xff0c;Mongodb适合保存大量的非业务数据&#xff0c;因此&#xff0c;Adhesive框架提倡把不是非常重要的非业务数据&#xff08;比如应用程序信息中心的日志、异常、状态数据&#xff0c;又比如WCF扩…...