从Qt 5.7开始,在开源版Qt中与Qt Charts模块同时引入的还包含一个Qt Data Visualization模块。该模块提供了一种开发复杂、动态且需要快速响应的3D可视化应用的方法,擅长于对深度图或者大量快速变化的数据(例如从多个传感器接收到的数据)进行可视化,一般用于对分析要求较高的行业,例如学术研究或医学。可以通过3D柱形图、3D散点图和3D曲面图等形式来展示数据,还可以实现在3D视图和2D视图之间进行切换,从而最大限度利用3D可视化数据的价值。要使用该模块,需要在安装Qt时选择安装Qt Data Visualization组件,还需要在项目文件.pro中添加如下代码:QT += datavisualization。另外,Qt Data Visualization模块需要OpenGL的支持。可以在main()函数的开头添加如下一行代码来明确定义渲染后端:qputenv("QSG_RHI_BACKEND", "opengl");
12.1 在Qt Widgets中使用数据可视化
在Qt Data Visualization模块中的QAbstract3DGraph类是所有3D图形的基类,它继承自QWindow和QOpenGLFunctions。该类无法直接使用,实际编程中,使用的是它的3个子类,分别是Q3DBars(3D柱形图)、Q3DScatter(3D散点图)和Q3DSurface(3D曲面图)。使用Qt Data Visualization模块,需要包含如下头文件:#include 。
12.1.1 3D柱形图
cpp
int main(int argc, char *argv[])
{
qputenv("QSG_RHI_BACKEND", "opengl");
QApplication a(argc, argv);
Q3DBars bars;
bars.setFlags(bars.flags() ^ Qt::FramelessWindowHint);
bars.resize(800, 600);
bars.rowAxis()->setRange(0, 1);
bars.columnAxis()->setRange(0, 3);
QBar3DSeries *series = new QBar3DSeries;
QBarDataRow *data = new QBarDataRow;
QBarDataRow *data1 = new QBarDataRow;
*data << 1.0f << 3.0f << 7.5f << 5.0f ;
*data1 << 2.0f << 1.0f << 4.0f << 3.5f;
series->dataProxy()->addRow(data);
series->dataProxy()->addRow(data1);
bars.addSeries(series);
bars.show();
return a.exec();
}
- 这里首先创建了Q3DBars的一个实例,因为要将其作为顶级窗口,所以要将它默认设置的Qt::FramelessWindowHint窗口类型清除掉。然后通过rowAxis()、columnAxis()来获取行和列的默认轴并设置了范围。
- QBar3DSeries类用来管理系列的可视化元素和数据。需要通过使用数据代理QBarDataProxy来添加数据,可以通过dataProxy()来获取默认的数据代理。系列中每一行的数据可以由QBarDataRow来指定,然后通过QBarDataProxy的addRow()将其添加到系列中。最后使用Q3DBars的addSeries()将系列添加到3D柱形图中,并调用show()进行显示。

12.1.2 自定义3D场景
- 3D场景是通过使用Q3DScene类实现的,场景中包含了一个活动相机(使用Q3DCamera类实现)和一个活动光源(使用Q3DLight类实现)。光源始终相对于相机定位,默认情况下,灯光位置会自动跟随相机。
- 可以通过指定相机的预设位置、旋转和缩放级别来定制相机。代码中可以使用Q3DBars的scene()函数来获取Q3DScene实例的指针,然后使用其activeCamera()函数获取场景中当前活动的相机。
- 对于Q3DCamera,可以使用setXRotation()、setYRotation()和setZoomLevel()等函数来设置相机的旋转和缩放,还可以使用setCameraPreset()来设置相机的位置,通过Q3DCamera::CameraPreset枚举类型提供了20多种预设的相机位置。
cpp
Q3DCamera *camera = bars.scene()->activeCamera();
camera->setCameraPreset(Q3DCamera::CameraPresetIsometricRightHigh);
camera->setZoomLevel(130);

12.1.3 设置轴标签、柱形标签和轴标题
- 在使用addRow()添加数据的时候就可以使用该函数的另外一种重载形式指定行标签,不过,也可以单独使用QBarDataProxy类的setRowLabels()来为所有行添加标签,使用setColumnLabels()来为所有列添加标签。对于3D柱形图中每个柱形的标签,可以使用QBar3DSeries的setItemLabelFormat()来设置,其中可以使用@rowLabel、@colLabel和@valueLabel等格式标记。

cpp
const QStringList rows = { "row0", "row1" };
const QStringList cols = { "col0", "col1", "col2", "col3" };
series->dataProxy()->setRowLabels(rows);
series->dataProxy()->setColumnLabels(cols);
series->setItemLabelFormat("@rowLabel, @colLabel: @valueLabel");

- 可以分别使用Q3DBars的rowAxis()、columnAxis()和valueAxis()来获取默认的3个轴, 3D柱形图的行和列坐标轴均为QCategory3DAxis,数值坐标轴为QValue3DAxis,这两类坐标轴都继承自QAbstract3DAxis。轴标题默认是不显示的,可以通过setTitleVisible(true)进行显示,使用setTitle()来设置轴标题。
- 轴上标签也可以随着相机的移动来自动改变角度,从而尽可能朝向相机,可以使用setLabelAutoRotation()来设置角度,取值范围为0~90。另外,可以通过orientation()来获取轴的方向,其结果由QAbstract3DAxis::AxisOrientation枚举类型指定,即X轴、Y轴和Z轴。
cpp
bars.rowAxis()->setTitle("Row");
bars.rowAxis()->setTitleVisible(true);
bars.columnAxis()->setTitle("Column");
bars.columnAxis()->setTitleVisible(true);
bars.valueAxis()->setTitle("Value");
bars.valueAxis()->setTitleVisible(true);
bars.columnAxis()->setLabelAutoRotation(60);
qDebug() << "rowAxis: " << bars.rowAxis()->orientation(); // Z轴
qDebug() << "columnAxis: " << bars.columnAxis()->orientation(); // X轴
qDebug() << "valueAxis: " << bars.valueAxis()->orientation(); // Y轴

12.1.4 设置3D项的形状
-
在QAbstract3DSeries中预定义了多个3D形状,如下表所列。

-
可以通过setMesh()为系列的项进行设置。还可以通过setMeshSmooth(true)来使3D形状显示更平滑。
cpp
series->setMesh(QAbstract3DSeries::MeshPyramid);
series->setMeshSmooth(true);
bars.setBarThickness(0.6);
bars.setBarSpacing(QSizeF(3.0, 2.0));
- 另外,Q3DBars中的setBarThickness()可以设置柱形条的宽窄,默认值为1.0,表示宽度和深度一样,如果设置为0.5,则表示深度是宽度的两倍。
- 可以使用setBarSpacing()来设置在X轴、Z轴上柱形条之间的空隙,默认值为(1.0, 1.0)。
- 还有一个setFloorLevel()可以设置Y轴的水平面位置,默认值为0,大于该值的柱形条会绘制在平面上方,小于该值的柱形条会绘制在平面下方。

12.1.5 设置主题
Q3DTheme类用来指定影响所有图形的视觉属性,Qt提供了几个内置的主题可以直接使用,也可以在这些现成主题上进行修改。可以通过Q3DBars的activeTheme()来获取主题对象,然后使用Q3DTheme的setType()来设置要使用的主题类型,可以通过Q3DTheme::Theme关键字查看所有主题类型。另外,还可以使用Q3DTheme类中众多的函数来自定义主题的相关属性。
cpp
bars.activeTheme()->setType(Q3DTheme::ThemeStoneMoss);
const QList<QColor> colors = { Qt::green };
bars.activeTheme()->setBaseColors(colors);
bars.activeTheme()->setSingleHighlightColor(Qt::red);

12.1.6 选择模式和切片视图
- 所有可视化类型都支持使用鼠标、触摸和编程的方式来选择单个数据项,被选中的项会进行突出显示。3D柱形图和3D曲面图还支持切片选择模式,可以将选中的行或列以伪2D图形的形式绘制在分离出来的视图中,这样可以很方便地查看单个行或列的实际值。
- 3D柱形图还支持在不打开切片视图的情况下突出显示所选柱形的整个行或列。通过设置选择模式,在3D柱形图中还支持通过单击轴标签来选择整个行或列。
- 可以使用QAbstract3DGraph的setSelectionMode()来设置选择模式。
cpp
bars.setSelectionMode(QAbstract3DGraph::SelectionRow | QAbstract3DGraph::SelectionSlice);

12.1.7 项目模型和数据映射
- 除了通过数据代理为3D柱形图添加数据外,每种可视化类型都为项目模型(QAbstractItemModel的子类)提供了专门的代理类,例如,用于QBar3DSeries的QItemModelBarDataProxy,用于Q3DScatter的QItemModelScatterDataProxy,以及用于Q3DSurface的QItemModelSurfaceDataProxy。
- 这些代理使用起来很简单,只需要为它们指定一个包含数据的项目模型的指针,然后设置映射规则即可。数据映射是基于项目模型的角色(role)的,需要为不同可视化类型提供不同角色的数据。对于特定的可视化类型,代理也支持其他一些功能,例如,QItemModelBarDataProxy可以将QAbstractItemModel的行和列直接映射到柱形图的行和列。
- 这里先使用QTableWidget来生成表格并保存数据,最后需要指定竖直和水平表头的标签内容。
cpp
QTableWidget *tableWidget = new QTableWidget(2, 3, this);
tableWidget->resize(360, 90);
tableWidget->move(220, 10);
QStringList days;
days << "Monday" << "Tuesday" << "Wednesday";
QStringList weeks;
weeks << "week 1" << "week 2";
// Mon Tue Wed
float expenses[2][3] = {{2.0f, 1.0f, 3.0f}, // week 1
{0.5f, 1.0f, 3.0f}}; // week 2
for (int week = 0; week < weeks.size(); week++) {
for (int day = 0; day < days.size(); day++) {
QModelIndex index = tableWidget->model()->index(week, day);
tableWidget->model()->setData(index, expenses[week][day]);
}
}
tableWidget->setVerticalHeaderLabels(weeks);
tableWidget->setHorizontalHeaderLabels(days);

cpp
Q3DBars *graph = new Q3DBars();
QWidget *container = QWidget::createWindowContainer(graph, this);
container->resize(780, 450);
container->move(10, 120);
Q3DCamera *camera = graph->scene()->activeCamera();
camera->setCameraPreset(Q3DCamera::CameraPresetIsometricRightHigh);
graph->activeTheme()->setType(Q3DTheme::ThemeIsabelle);
因为所有数据可视化图形类都继承自QWindow,所以它们无法直接作为QWidget的子部件,需要使用QWidget::createWindowContainer()来创建一个QWidget窗口容器,从而将QWindow嵌入到基于QWidget的应用中。
cpp
QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(tableWidget->model());
proxy->setUseModelCategories(true);
QBar3DSeries *series = new QBar3DSeries(proxy);
series->setMesh(QAbstract3DSeries::MeshPyramid);
graph->addSeries(series);
graph->setSelectionMode(QAbstract3DGraph::SelectionRow | QAbstract3DGraph::SelectionSlice);
创建QItemModelBarDataProxy实例时需要指定数据模型,通过setUseModelCategories(true)可以直接使用模型中的行和列映射到3D柱形图的行和列,并使用Qt::DisplayRole指定的数据作为柱形项的数值。

12.1.8 3D散点图和3D曲面图
- Q3DScatter用于创建3D散点图,它将数据呈现为一些点的集合。QScatter3DSeries和QScatterDataProxy用于将数据设置到图形,以及控制图形的可视属性。可以分别通过Q3DScatter的axisX()、axisY()和axisZ()来获取3个坐标轴,它们都是QValue3DAxis数值坐标轴。
cpp
Q3DScatter scatter;
scatter.setFlags(scatter.flags() ^ Qt::FramelessWindowHint);
scatter.resize(800, 600);
QScatter3DSeries *series = new QScatter3DSeries;
QScatterDataArray data;
data << QVector3D(0.5f, 0.5f, 0.5f) << QVector3D(-0.3f, -0.5f, -0.4f) << QVector3D(0.0f, -0.3f, 0.2f);
series->dataProxy()->addItems(data);
scatter.addSeries(series);
scatter.show();

- Q3DSurface用于将数据呈现为3D曲面图,QSurface3DSeries和 QSurfaceDataProxy用于为图形设置数据,以及控制图形的可视属性。与Q3DScatter一样,可以通过Q3DSurface的axisX()、axisY()和axisZ()来获取3个坐标轴,它们都是QValue3DAxis数值坐标轴。
cpp
Q3DSurface surface;
surface.setFlags(surface.flags() ^ Qt::FramelessWindowHint);
surface.resize(800, 600);
QSurfaceDataArray *data = new QSurfaceDataArray;
QSurfaceDataRow *dataRow1 = new QSurfaceDataRow;
QSurfaceDataRow *dataRow2 = new QSurfaceDataRow;
*dataRow1 << QVector3D(0.0f, 0.1f, 0.5f) << QVector3D(1.0f, 0.5f, 0.5f);
*dataRow2 << QVector3D(0.0f, 1.8f, 1.0f) << QVector3D(1.0f, 1.2f, 1.0f);
*data << dataRow1 << dataRow2;
QSurface3DSeries *series = new QSurface3DSeries;
series->dataProxy()->resetArray(data);
surface.addSeries(series);
surface.show();

- Q3DSurface还可以使用QHeightMapSurfaceDataProxy数据代理对高度图数据进行处理,从而将高度图可视化为3D曲面图,显示出3D地形图的效果。
cpp
Q3DSurface surface1;
surface1.setFlags(surface1.flags() ^ Qt::FramelessWindowHint);
surface1.resize(800, 600);
surface1.activeTheme()->setType(Q3DTheme::ThemeStoneMoss);
QSurface3DSeries *series1 = new QSurface3DSeries;
QHeightMapSurfaceDataProxy *proxy = new QHeightMapSurfaceDataProxy("../my3dsurface/layer.png");
series1->setDataProxy(proxy);
series1->setDrawMode(QSurface3DSeries::DrawSurface);
surface1.addSeries(series1);
surface1.show();
可以看到,只需要使用QHeightMapSurfaceDataProxy指定高度图的路径即可,为了显示更清晰,一般会设置setDrawMode(QSurface3DSeries::DrawSurface),这样只绘制曲面而不再绘制网格。

12.2 在Qt Quick中使用数据可视化
在Qt Data Visualization模块中的AbstractGraph3D类型是Qt Quick中所有3D图形的基类型,其3个子类型分别是Bars3D(3D柱形图)、Scatter3D(3D散点图)和Surface3D(3D曲面图)。要使用这些QML类型,需要使用如下导入语句:import QtDataVisualization
12.2.1 3D柱形图
- Qt Quick中Bars3D类型用来创建3D柱形图,Bar3DSeries和BarDataProxy用来为图形设置数据并控制图形的可视化属性。BarDataProxy作为3D柱形图的数据代理,可以处理数据行的添加、插入、更改、移除等操作,但是该类型无法直接创建,编程中要使用其子类型ItemModelBarDataProxy。
- Bars3D类型用来渲染3D柱形图,在其中需要使用Bar3DSeries来设置数据系列,Bar3DSeries除了管理可视化元素以外,还需要通过数据代理ItemModelBarDataProxy来设置系列的数据。
css
Window {
visible: true; width: 640; height: 480
Bars3D {
width: parent.width
height: parent.height
Bar3DSeries {
itemLabelFormat: "@colLabel, @rowLabel: @valueLabel"
ItemModelBarDataProxy {
itemModel: dataModel
rowRole: "year"
columnRole: "city"
valueRole: "expenses"
}
}
}
ListModel {
id: dataModel
ListElement{ year: "2012"; city: "Oulu"; expenses: "4200"; }
... ...
}
}
这里的数据是通过ListModel提供的,在ItemModelBarDataProxy中由itemModel属性指定了数据模型,然后通过rowRole、columnRole和valueRol这3个属性将模型中的角色与3D柱形系列的行、列和数值进行映射。

12.2.2 3D坐标轴
Qt Data Visualization中支持数值坐标轴ValueAxis3D和分类坐标轴CategoryAxis3D,它们都继承自AbstractAxis3D类型。与Qt Charts类似,如果没有明确指定坐标轴,那么会创建一个没有标签的临时默认坐标轴。但是如果在一个方向上指定了坐标轴,那么该方向上的默认坐标轴就会被销毁。
css
Bars3D {
width: parent.width; height: parent.height
rowAxis: rAxis; columnAxis: cAxis; valueAxis: vAxis
Bar3DSeries {
itemLabelFormat: "@colLabel, @rowLabel: @valueLabel"
ItemModelBarDataProxy {
itemModel: dataModel
rowRole: "year"; columnRole: "month"; valueRole: "income"
}
}
}
ValueAxis3D {
id: vAxis
title: "Y-Axis"; titleVisible: true
min: 0; max: 30
subSegmentCount: 2
labelFormat: "%.1f"
}
CategoryAxis3D {
id: rAxis
title: "Z-Axis"; titleVisible: true; labelAutoRotation: 30
}
CategoryAxis3D {
id: cAxis
title: "X-Axis"; titleVisible: true
labels: ["January", "February"]
labelAutoRotation: 30
}
这里通过ValueAxis3D和两个CategoryAxis3D定义了3个坐标轴,分别设置为了Bars3D的行坐标轴、列坐标轴和数值坐标轴。对于ValueAxis3D,它与Qt Charts中的ValueAxis类似;CategoryAxis3D与Qt Charts中的CategoryAxis也很类似,这里在cAxis中还设置了其labels属性,因为该轴上对应的数据month为数值,显示不够友好,所以这里进行了设置;而labelAutoRotation属性可以设置标签的可旋转角度。

12.2.3 数据代理
- 除了在Bar3DSeries中使用的ItemModelBarDataProxy,3D散点图、3D曲面图也有自己的数据代理,相关类型的继承关系如图所示。

- 通过ItemModelBarDataProxy可以使用AbstractItemModel派生出的模型作为3D柱形图 Bars3D的数据源,当映射或模型改变时,数据会进行异步解析。默认情况下映射的数据会自动生成行分类和列分类,但有时候可能只想显示某些分类的内容,这时可以通过ItemModelBarDataProxy类型的rowCategories和columnCategories来明确指定需要显示的行、列分类,同时还需要设置autoRowCategories、autoColumnCategories为false,这样才能使设置的分类生效。例如:
css
rowCategories: ["2019"]
autoRowCategories: false
columnCategories: ["01"]
autoColumnCategories: false
- 有时候模型提供的数据并不是直接可用的,比如角色timestamp的值为2006-01,而实际需要的是里面的年份2006和月份01,这时就需要对这个timestamp的数据进行处理。在ItemModelBarDataProxy中提供了rowRolePattern和columnRolePattern来使用正则表达式分别对行和列映射来的数据进行查找和替换,然后再作为分类使用。rowRolePattern和columnRolePattern属性可以指定一个正则表达式来找到需要替换的那部分数据,而对应的rowRoleReplace和columnRoleReplace两个属性则用来指定具体要替换的内容。
css
ItemModelBarDataProxy {
itemModel: dataModel
rowRole: "timestamp"
columnRole: "timestamp"
valueRole: "income"
rowRolePattern: /^(\d\d\d\d).*$/
columnRolePattern: /^.*-(\d\d)$/
rowRoleReplace: "\\1"
columnRoleReplace: "\\1"
multiMatchBehavior: ItemModelBarDataProxy.MMBCumulative
}
css
ListModel {
id: dataModel
ListElement{ timestamp: "2006-01"; expenses: "-4"; income: "5" }
ListElement{ timestamp: "2006-02"; expenses: "-5"; income: "6" }
ListElement{ timestamp: "2006-02"; expenses: "-5"; income: "4" }
}
这里行和列需要的年、月信息都包含在timestamp角色中,所以rowRole和columnRole都指定为了该角色,然后通过设置搜索表达式和替换字符串来获取timestamp中需要的那部分字段。具体来说,对于rowRole,这里获取了timestamp字符串中第一个捕获的2006,然后使用2006把整个timestamp字符串进行替换,这样就只保留了年份信息;类似的,对于columnRole只保留了月份信息。这里指定的ItemModelBarDataProxy.MMBCumulative表明会使用所有匹配到的数据的总和作为条形的数值。

12.2.4 3D系列
3D柱形系列Bar3DSeries以及Scatter3DSeries、Surface3DSeries都继承自Abstract3DSeries。在Abstract3DSeries中定义了一些基本的属性,比如颜色、项目标签、高亮颜色等,其中mesh属性指定了3D图形中单个项目的形状。另外,可以设置meshSmooth为true来显示3D图形的光滑版本。
css
mesh: Abstract3DSeries.MeshPyramid
baseColor: "gold"
singleHighlightColor: "lightgreen"
itemLabelVisible: false
meshAngle: 30

12.2.5 自定义3D场景
通过Scene3D类型可以设置3D场景,其中包含了一个由Camera3D指定的相机和一个由Light3D指定的光源,光源位置始终与相机相对应,默认情况下,光源位置会自动跟随相机。在代码中,一般可以通过scene.activeCamera来获取图形关联的场景的活动相机,从而进行相关设置。对于Camera3D,其cameraPreset属性可以设置预设的相机位置,提供了20多个现成的位置进行设置,可以参考Q3DCamera::CameraPreset;如果没有通过cameraPreset设置相机位置,那么也可以使用xRotation和yRotation来设置相机的角度。
css
scene{
activeCamera.cameraPreset:
Camera3D.CameraPresetIsometricRightHigh
activeCamera.zoomLevel: 120
}
css
scene{
activeCamera.xRotation: -30
activeCamera.yRotation: 45
activeCamera.zoomLevel: 120
}

12.2.6 设置主题
- Qt Data Visualization中可以通过Theme3D类型来设置主题,其中内建了9种现成的主题,可以在帮助中通过Q3DTheme::Theme关键字进行查看。这些主题是通过一些可视元素的样式设置的集合,其中包含了颜色、字体、光照强度、环境光强度等。
- 在编程中可以直接使用现成的主题,也可以在这些主题的基础上进行修改,如果对所有主题都不满意,那么可以直接(当不指定主题时,默认使用Theme3D.ThemeUserDefined)从头来创建一个主题。
css
Window {
... ...
ThemeColor { id: dynamicColor; color: "gold" }
ThemeColor { id: dynamicColor2; color: "lightgreen"}
Theme3D {
id: userDefinedTheme
ambientLightStrength: 0.5
backgroundColor: "transparent"; backgroundEnabled: true
baseColors: [dynamicColor, dynamicColor2]
colorStyle: Theme3D.ColorStyleUniform
font.pointSize: 35; font.bold: true
gridLineColor: "grey"
highlightLightStrength: 0.5
labelBackgroundColor: "transparent"
labelBorderEnabled: false; labelTextColor: "white"
lightColor: "white"; lightStrength: 7.0
singleHighlightColor: "lightblue"
windowColor: "black"
}
Bars3D {theme: userDefinedTheme // 指定主题... ...}

12.2.7 选择模式和切片视图
所有可视化类型都支持使用鼠标、触摸和编程的方式来选择单个数据项,被选中的项目会进行突出显示。3D柱形图和3D曲面图还支持切片选择模式,可以将选中的行或列以伪2D图形的形式绘制在分离出来的视图中,这样可以很方便地查看单个行或列的实际值。3D柱形图还支持在不打开切片视图的情况下突出显示所选柱形的整个行或列。通过设置选择模式,在3D柱形图中还支持通过单击轴标签来选择整个行或列。要实现2D切片视图,只需要在Bars3D对象中添加如下一行代码:
css
selectionMode: AbstractGraph3D.SelectionItemAndRow | AbstractGraph3D.Selectio

12.2.8 3D散点图
3D散点图Scatter3D通过一系列点来展示数据,与其对应的系列和数据代理分别是Scatter3DSeries和ScatterDataProxy。3D散点图的三个轴axisX、axisY和axisZ都是ValueAxis3D类型的。
css
Scatter3D {
width: parent.width; height: parent.height
axisX: xAxis; axisY: yAxis; axisZ: zAxis
scene{
activeCamera.cameraPreset:
Camera3D.CameraPresetIsometricRightHigh
activeCamera.zoomLevel: 120
}
theme: Theme3D { type: Theme3D.ThemeStoneMoss;
font.pointSize: 35
}
Scatter3DSeries {
ItemModelScatterDataProxy {
itemModel: dataModel
xPosRole: "xPos"; yPosRole: "yPos";
zPosRole: "zPos"
}
}
}
css
ValueAxis3D {
id: xAxis
title: "X-Axis"; titleVisible: true
min: 1; max: 5; subSegmentCount: 2
labelFormat: "%.2f"; labelAutoRotation: 45
}
ValueAxis3D { id: yAxis; ......}
ValueAxis3D { id: zAxis; ......}
ListModel {
id: dataModel
ListElement{ xPos: "2.754"; yPos: "1.455";
zPos: "3.362"; }
... ...
}

12.2.9 3D曲面图
- 3D曲面图Surface3D通过设置点形成一个曲面来展示数据,与其对应的系列和数据代理分别是Surface3DSeries和SurfaceDataProxy。3D曲面图的3个轴也都是ValueAxis3D类型的。
css
Surface3D {
width: parent.width
height: parent.height
Surface3DSeries {
itemLabelFormat: "Pop density at (@xLabel N, @zLabel E): @yLabel"
ItemModelSurfaceDataProxy {
itemModel: dataModel
rowRole: "longitude"
columnRole: "latitude"
yPosRole: "pop_density"
}
}
}
ListModel {
id: dataModel
ListElement{ longitude: "20"; latitude: "10";
pop_density: "4.75"; }
... ...
}

- 在3D曲面图中还有一个HeightMapSurfaceDataProxy数据代理,它可以将一个高度图可视化为一个3D曲面图从而显示出3D地形图的效果,这个代理使用起来也非常简单,只需要指定一个高度图路径即可。
css
Surface3D {
width: parent.width; height: parent.height
shadowQuality: AbstractGraph3D.ShadowQualityNone
scene{ activeCamera.cameraPreset:
Camera3D.CameraPresetIsometricLeft }
axisY{ min: 20; max: 200; segmentCount: 5;
subSegmentCount: 2; labelFormat: "%i" }
axisX{...}
axisZ{...}
Surface3DSeries {
baseGradient: layerGradient
drawMode: Surface3DSeries.DrawSurface
flatShadingEnabled: false
HeightMapSurfaceDataProxy {
heightMapFile:
"../mydatavisualization/layer.png"
}}}
