概述
本教程提供了使用内核功能进行测量的使用教程
描述
通过使用内核功能测量距离、周长、面积、体积
示例代码
效果图

main.cpp
#include <QApplication>
#include "MWindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MWindow w;
w.show();
return a.exec();
}
MWindow.h
#pragma once
#include <QMainWindow>
#include "ui_MWindow.h"
#include"common.h"
#include "DlgMeasurement.h"
#include<QActionGroup>
class MWindow : public QMainWindow
{
Q_OBJECT
public:
MWindow(QWidget *parent = nullptr);
~MWindow();
void LoadModel();
AMCAX::TopoShape FindToposhaeById(AMCAXRender::EntityId id) {
if (mShapsSet.count(id) > 0) {
return mShapsSet[id];
}
return AMCAX::TopoShape();
}
protected:
void logMessage(const QString& message);
private:
Ui::MWindowClass ui;
std::shared_ptr<AMCAXRender::IRenderComponent> mRenderComponent;
std::shared_ptr<AMCAXRender::CBasicRender> mRender;
DlgMeasurement* dlgDistance;
QActionGroup* mActGroup;
std::unordered_map<AMCAXRender::EntityId, AMCAX::TopoShape> mShapsSet;
};
MWindow.h
#include "MWindow.h"
#include<QDateTime>
MWindow::MWindow(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
mRender = mRenderComponent->CreateBasicRender();
ui.gridLayout->addWidget(mRender->widget);
LoadModel();
dlgDistance = new DlgMeasurement(mRender,this);
mActGroup = new QActionGroup(this);
ui.actionDistanceMeasure->setData(DlgMeasurement::kDistance);
ui.actionLenghtMeasure ->setData(DlgMeasurement::kLength);
ui.actionSquareMeasure ->setData(DlgMeasurement::kSquare);
ui.actionAngleMeasure ->setData(DlgMeasurement::kAngle);
ui.actionVolumeMeasure ->setData(DlgMeasurement::kVolume);
mActGroup->addAction(ui.actionDistanceMeasure);
mActGroup->addAction(ui.actionLenghtMeasure);
mActGroup->addAction(ui.actionSquareMeasure);
mActGroup->addAction(ui.actionAngleMeasure);
mActGroup->addAction(ui.actionVolumeMeasure );
connect(mActGroup, &QActionGroup::triggered, this, [this](QAction* act) {
DlgMeasurement::MeasureType type =(DlgMeasurement::MeasureType)qobject_cast<QAction*>(act)->data().toInt();
dlgDistance->showPage(type);
});
}
MWindow::~MWindow()
{}
void MWindow::LoadModel()
{
AMCAX::TopoShape cube = AMCAX::MakeBox(10.0, 10.0, 10.0);
auto cubeEntity = mRender->entityFactory->FromShape(cube);
mRender->entityManage->AddEntity(cubeEntity);
mShapsSet[cubeEntity->GetEntityId()] = cube;
AMCAX::Frame3 frame(AMCAX::Point3(20., 0., 0.), AMCAX::Direction3(1.0, 0.0, 1.0));
double radius = 2.0;
double height = 5.0;
auto cylinder = AMCAX::MakeCylinder(frame, radius, height).Shape();
auto cylinderEntity = mRender->entityFactory->FromShape(cylinder);
mRender->entityManage->AddEntity(cylinderEntity);
mShapsSet[cylinderEntity->GetEntityId()] = cylinder;
mRender->cameraManage->ResetCamera();
mRender->entityManage->DoRepaint();
}
void MWindow::logMessage(const QString& message)
{
QDateTime currentTime = QDateTime::currentDateTime();
QString timestamp = currentTime.toString("yyyy-MM-dd HH:mm:ss");
ui.textEdit->append(QString("[%1] %2").arg(timestamp, message));
}
AMCAX_RENDER_API std::shared_ptr< IRenderComponent > CreateRenderComponent(QWidget *parent)
Create Render Component
MWindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MWindowClass</class>
<widget class="QMainWindow" name="MWindowClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>测量示例</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="5,1">
<item>
<layout class="QGridLayout" name="gridLayout"/>
</item>
<item>
<widget class="QTextEdit" name="textEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionDistanceMeasure"/>
<addaction name="actionLenghtMeasure"/>
<addaction name="actionAngleMeasure"/>
<addaction name="actionSquareMeasure"/>
<addaction name="actionVolumeMeasure"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionDistanceMeasure">
<property name="text">
<string>距离测量</string>
</property>
<property name="menuRole">
<enum>QAction::NoRole</enum>
</property>
</action>
<action name="actionLenghtMeasure">
<property name="text">
<string>长度测量</string>
</property>
<property name="menuRole">
<enum>QAction::NoRole</enum>
</property>
</action>
<action name="actionAngleMeasure">
<property name="text">
<string>角度测量</string>
</property>
<property name="menuRole">
<enum>QAction::NoRole</enum>
</property>
</action>
<action name="actionSquareMeasure">
<property name="text">
<string>面积测量</string>
</property>
<property name="menuRole">
<enum>QAction::NoRole</enum>
</property>
</action>
<action name="actionVolumeMeasure">
<property name="text">
<string>体积测量</string>
</property>
<property name="menuRole">
<enum>QAction::NoRole</enum>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
DlgMeasurement.h
#pragma once
#include <QDialog>
#include "ui_DlgMeasurement.h"
#include"common.h"
class MWindow;
struct PickInfo;
class DlgMeasurement : public QDialog
{
Q_OBJECT
public:
enum MeasureType
{
kDistance,
kLength,
kSquare,
kAngle,
kVolume,
};
DlgMeasurement(std::shared_ptr<AMCAXRender::CBasicRender> render, MWindow *parent = nullptr);
~DlgMeasurement();
void showPage(MeasureType t);
protected:
void closeEvent(QCloseEvent* event) override;
void clearData();
void calcDistance();
void calcLength();
void calcSquare();
void calcAngle();
void calcVolume();
private:
Ui::DlgMeasurementClass ui;
std::shared_ptr<AMCAXRender::CBasicRender> mRender;
MWindow* minWindow;
PickInfo mPickInf[2];
MeasureType mCurrentType;
};
DlgMeasurement.h
#include "DlgMeasurement.h"
#include "MWindow.h"
#include <topology/BRepExtremaDistShapeShape.hpp>
#include <nurbs/NURBSAPIGetGeometry.hpp>
#include <geometry/ComputePointsAbscissa.hpp>
#include <topology/BRepGlobalProperty.hpp>
#include <geometry/GlobalProperty.hpp>
#include <topology/TopoTool.hpp>
DlgMeasurement::DlgMeasurement(std::shared_ptr<AMCAXRender::CBasicRender> render, MWindow* parent)
: QDialog(parent)
, mRender(render)
, minWindow(parent)
{
ui.setupUi(this);
this->setFocusPolicy(Qt::FocusPolicy::NoFocus);
[&](AMCAXRender::EntityId parentId, AMCAXRender::EntityId entityId,
AMCAXRender::PickType type,
int subIndex,
int* pos) {
PickInfo currentPickInfo = { entityId ,type,subIndex };
if (ui.pushButton->isChecked()) {
if (currentPickInfo.type != AMCAXRender::PickType::unknown) {
mRender->entityManage->RemoveHightLight(mPickInf[0].entityId, mPickInf[0].type, mPickInf[0].subIndex);
mPickInf[0] = currentPickInfo;
ui.pushButton->setText(mPickInf[0].GetMessage());
mRender->entityManage->AddHightLight(mPickInf[0].entityId, mPickInf[0].type, mPickInf[0].subIndex);
ui.pushButton->setChecked(false);
}
}
if (ui.pushButton_2->isChecked()) {
if (currentPickInfo.type != AMCAXRender::PickType::unknown) {
mRender->entityManage->RemoveHightLight(mPickInf[1].entityId, mPickInf[1].type, mPickInf[1].subIndex);
mPickInf[1] = currentPickInfo;
ui.pushButton_2->setText(mPickInf[1].GetMessage());
mRender->entityManage->AddHightLight(mPickInf[1].entityId, mPickInf[1].type, mPickInf[1].subIndex);
ui.pushButton_2->setChecked(false);
}
}
}
);
connect(ui.pushButton_3, &QPushButton::clicked, this, [this]() {
switch (mCurrentType)
{
case DlgMeasurement::kDistance:
calcDistance();
break;
case DlgMeasurement::kLength:
calcLength();
break;
case DlgMeasurement::kSquare:
calcSquare();
break;
case DlgMeasurement::kAngle:
calcAngle();
break;
case DlgMeasurement::kVolume:
calcVolume();
break;
default:
break;
}
});
}
DlgMeasurement::~DlgMeasurement()
{}
void DlgMeasurement::showPage(MeasureType t)
{
switch (t)
{
case DlgMeasurement::kDistance:
ui.widget->setVisible(true);
ui.widget_2->setVisible(true);
this->setWindowTitle("距离测量");
break;
case DlgMeasurement::kLength:
ui.widget->setVisible(true);
ui.widget_2->setVisible(false);
this->setWindowTitle(("长度测量"));
break;
case DlgMeasurement::kSquare:
ui.widget->setVisible(true);
ui.widget_2->setVisible(false);
this->setWindowTitle(("面积测量"));
break;
case DlgMeasurement::kAngle:
ui.widget->setVisible(true);
ui.widget_2->setVisible(true);
this->setWindowTitle(("角度测量"));
break;
case DlgMeasurement::kVolume:
ui.widget->setVisible(true);
ui.widget_2->setVisible(false);
this->setWindowTitle(("体积测量"));
break;
default:
break;
}
mCurrentType = t;
clearData();
show();
}
void DlgMeasurement::closeEvent(QCloseEvent* event)
{
QDialog::closeEvent(event);
clearData();
}
void DlgMeasurement::clearData()
{
mRender->entityManage->ClearHightLight();
mRender->entityManage->DoRepaint();
ui.label_3->clear();
ui.pushButton->setText("拾取");
ui.pushButton_2->setText("拾取");
ui.buttonGroup->setExclusive(false);
ui.pushButton->setChecked(false);
ui.pushButton_2->setChecked(false);
ui.buttonGroup->setExclusive(true);
}
void DlgMeasurement::calcDistance()
{
auto shape1 = FindSubShape(minWindow->FindToposhaeById(mPickInf[0].entityId), PickTypeToShapeType(mPickInf[0].type), mPickInf[0].subIndex);
auto shape2 = FindSubShape(minWindow->FindToposhaeById(mPickInf[1].entityId), PickTypeToShapeType(mPickInf[1].type), mPickInf[1].subIndex);
if (shape1.IsNull() || shape2.IsNull()) {
return ;
}
AMCAX::BRepExtremaDistShapeShape compute(shape1, shape2);
if (compute.Perform()) {
double dist = compute.Value();
auto point1 = compute.PointOnShape1(0);
auto point2 = compute.PointOnShape2(0);
AMCAX::Vector3 v_1(point1, point2);
auto x = std::abs(v_1.X());
auto y = std::abs(v_1.Y());
auto z = std::abs(v_1.Z());
auto text = QString("distance : %1 \nx : %2 \ny : %3 \nz : %4 \n")
.arg(QString::number(dist))
.arg(QString::number(x))
.arg(QString::number(y))
.arg(QString::number(z));
ui.label_3->setText(text);
}
}
void DlgMeasurement::calcLength()
{
auto shape1 = FindSubShape(minWindow->FindToposhaeById(mPickInf[0].entityId), PickTypeToShapeType(mPickInf[0].type), mPickInf[0].subIndex);
if (shape1.IsNull() ) {
return ;
}
auto edge =
static_cast<const AMCAX::TopoEdge&
>(shape1);
auto curve3 = AMCAX::NURBSAPIGetGeometry::GetCurve(edge);
AMCAX::AdaptorGeom3Curve adaptor(curve3);
AMCAX::ComputePointsAbscissa compute1(adaptor, 0.001, curve3->FirstParameter());
double length = compute1.Length(adaptor);
ui.label_3->setText(QString::number( length));
}
void DlgMeasurement::calcSquare()
{
auto shape1 = FindSubShape(minWindow->FindToposhaeById(mPickInf[0].entityId), PickTypeToShapeType(mPickInf[0].type), mPickInf[0].subIndex);
if (shape1.IsNull()) {
return ;
}
AMCAX::GlobalProperty prop;
AMCAX::BRepGlobalProperty::SurfaceProperties(shape1, prop);
auto v = prop.Mass();
ui.label_3->setText(QString::number(v));
}
void DlgMeasurement::calcAngle()
{
auto edge1 = static_cast<const AMCAX::TopoEdge&>(FindSubShape(minWindow->FindToposhaeById(mPickInf[0].entityId), PickTypeToShapeType(mPickInf[0].type), mPickInf[0].subIndex));
auto edge2 = static_cast<const AMCAX::TopoEdge&>(FindSubShape(minWindow->FindToposhaeById(mPickInf[1].entityId), PickTypeToShapeType(mPickInf[1].type), mPickInf[1].subIndex));
if (edge1.IsNull() || edge2.IsNull()) {
return ;
}
double f, l;
auto flag1 = AMCAX::TopoTool::Curve(edge1, f, l)->Type() != AMCAX::CurveType::Line;
auto flag2 = AMCAX::TopoTool::Curve(edge2, f, l)->Type() != AMCAX::CurveType::Line;
if (flag1 || flag2) {
return;
}
AMCAX::TopoVertex vfirst;
AMCAX::TopoVertex vlast;
AMCAX::TopoExplorerTool::Vertices(edge1, vfirst, vlast);
AMCAX::Point3 pt1 = AMCAX::TopoTool::Point(vfirst);
AMCAX::Point3 pt2 = AMCAX::TopoTool::Point(vlast);
AMCAX::Vector3 v_1(pt1,pt2);
v_1.Normalize();
AMCAX::TopoVertex vfirst2;
AMCAX::TopoVertex vlast2;
AMCAX::TopoExplorerTool::Vertices(edge2, vfirst2, vlast2);
AMCAX::Point3 pt3 = AMCAX::TopoTool::Point(vfirst2);
AMCAX::Point3 pt4 = AMCAX::TopoTool::Point(vlast2);
AMCAX::Vector3 v_2(pt3, pt4);
v_2.Normalize();
auto angle = v_1.Angle(v_2) * 180.0 / M_PI;
ui.label_3->setText(QString::number(angle));
}
void DlgMeasurement::calcVolume()
{
auto shape1 = minWindow->FindToposhaeById(mPickInf[0].entityId);
if (shape1.IsNull()) {
return ;
}
AMCAX::GlobalProperty prop;
AMCAX::BRepGlobalProperty::VolumeProperties(shape1, prop);
auto v = prop.Mass();
ui.label_3->setText(QString::number(v));
}
PickType
Pick Type
定义 Constants.h:99
@ edge
Edge Pick
定义 Constants.h:103
@ body
Body Pick
定义 Constants.h:105
@ all
All Pick
定义 Constants.h:106
@ face
Face Pick
定义 Constants.h:104
@ mouse_click
Left Click
定义 Constants.h:84
DlgMeasurement.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DlgMeasurementClass</class>
<widget class="QDialog" name="DlgMeasurementClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>243</height>
</rect>
</property>
<property name="windowTitle">
<string>距离测量</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="2,1,0">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>拾取对象</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>拾取对象</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>拾取</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>拾取对象</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>拾取</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>测量结果</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>0.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>计算</string>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
<buttongroups>
<buttongroup name="buttonGroup"/>
</buttongroups>
</ui>
common.h
#pragma once
#include <modeling/MakeShapeTool.hpp>
#include <topology/TopoFace.hpp>
#include <topology/TopoExplorerTool.hpp>
#include <topology/TopoVertex.hpp>
#include <topology/BRepAdaptorCurve3.hpp>
#include <geometry/Geom3Curve.hpp>
#include <modeling/MakeBox.hpp>
#include <modeling/MakeCylinder.hpp>
#include<qstring.h>
struct PickInfo
{
AMCAXRender::EntityId entityId;
int subIndex = 0;
QString GetMessage() {
return QString("%1 : %2").arg(GetTypeName(type)).arg(QString::number(subIndex));
}
};
AMCAX::TopoShape FindSubShape(const AMCAX::TopoShape& shape, AMCAX::ShapeType type, int subIdex);
common.cpp
#include"common.h"
{
QString name;
switch (type)
{
case AMCAXRender::PickType::unknown:
name = "unknown";
break;
name = "vert";
break;
name = "edge";
break;
name = "face";
break;
name = "body";
break;
default:
break;
}
return name;
}
{
switch (t)
{
return AMCAX::ShapeType::Vertex;
break;
return AMCAX::ShapeType::Edge;
return AMCAX::ShapeType::Face;
return AMCAX::ShapeType::Shape;
}
return AMCAX::ShapeType::Shape;
}
AMCAX::TopoShape FindSubShape(const AMCAX::TopoShape& shape, AMCAX::ShapeType type, int subIdex) {
AMCAX::IndexSet<AMCAX::TopoShape> sets;
AMCAX::TopoExplorerTool::MapShapes(shape, type, sets);
if (subIdex < sets.size()) {
return sets[subIdex];
}
return AMCAX::TopoShape();
}
@ point
Point Pick
定义 Constants.h:102
@ vert
Vertex Pick
定义 Constants.h:101
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(plugin_Texture)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
add_definitions(-DUSE_AMCAX_KERNEL)
set(AMCAX_components AMCAXCommon AMCAXPart AMCAXStep AMCAXOCCTIO)
find_package(AMCAXCommon REQUIRED)
find_package(AMCAXStep REQUIRED)
find_package(AMCAXPart REQUIRED)
find_package(AMCAXOCCTIO REQUIRED)
list(APPEND CMAKE_PREFIX_PATH ${AMCAXRender_PATH})
find_package(AMCAXRender )
find_package(Qt6 COMPONENTS Widgets Core Gui REQUIRED)
file(GLOB ALL_UI_FILES *.ui)
file(GLOB ALL_FILES *.cpp *.h)
add_executable(${PROJECT_NAME} ${ALL_UI_FILES} ${ALL_FILES})
target_link_libraries(${PROJECT_NAME} PRIVATE ${AMCAX_components})
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)
target_link_libraries(${PROJECT_NAME} PRIVATE AMCAXRender::AMCAXRender)
更多
更多属性请参考 AMCAXRender::TextureProp3D