You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmPlot/nmObjLineCrack.cpp

508 lines
13 KiB
C++

#include <QPainter>
#include <ZxSerializer.h>
#include "IxPtyPano.h"
#include "ZxBaseUtil.h"
#include "ZxSubAxisX.h"
#include "ZxSubAxisY.h"
#include "nmObjLineCrackTool.h"
#include "ZxPlot.h"
#include "ZxObjText.h"
#include "nmObjLineCrack.h"
#include "nmDataAnalyzeManager.h"
ZX_DEFINE_DYNAMIC(nObjLineFracture, nmObjLineCrack)
nmObjLineCrack::nmObjLineCrack()
{
m_sObjTag = "nObjLineFracture";
nmObjLineCrack::init("", NULL, NULL);
}
nmObjLineCrack::nmObjLineCrack(const QString& sName, \
ZxSubAxisX* pAxisX, \
ZxSubAxisY* pAxisY)
{
m_sObjTag = "nObjLineFracture";
nmObjLineCrack::init(sName, pAxisX, pAxisY);
}
nmObjLineCrack::~nmObjLineCrack()
{
if(m_fractureData != nullptr) {
delete m_fractureData;
m_fractureData = nullptr;
}
}
void nmObjLineCrack::init(const QString& sName, \
ZxSubAxisX* pAxisX, \
ZxSubAxisY* pAxisY)
{
nmObjBase::init(sName, pAxisX, pAxisY);
nmObjLineCrack::initFlags();
m_oPen = QPen(QBrush(Qt::red), \
0.3f, Qt::SolidLine);
m_fractureData = nullptr;
loadTempl();
// 连接图元可见性信号和槽
connect(this, SIGNAL(sigObjVisibleChanged(bool)),
this, SLOT(onObjVisibleChanged(bool)));
}
void nmObjLineCrack::initTools()
{
m_pTool = new nmObjLineCrackTool();
nmObjBase::initTools();
}
void nmObjLineCrack::initFlags()
{
setLockPos(false);
setLockSize(false);
setReadOnly(false);
}
bool nmObjLineCrack::hitTest(const QPointF& pt)
{
return nmObjBase::hitTest(pt);
}
bool nmObjLineCrack::_runHitTest(const QPointF& pt, int& nOption, int& nSubIndex)
{
if(!nmObjBase::_runHitTest(pt, nOption, nSubIndex)) {
return false;
}
nOption = -1;
nSubIndex = 0;
if(NULL == m_pAxisX || NULL == m_pAxisY) {
return false;
}
QVector<QPointF> pts = getPosOf(m_vecPoints);
// 点
double r = 1.f;
for(int i = 0; i < pts.count(); i++) {
QPointF ptTopLeft = QPointF(pts[i].x() - r,
pts[i].y() - r);
QSizeF sz = QSizeF(r * 2.f, r * 2.f);
QRectF rt = QRectF(ptTopLeft, sz);
bool b = rt.contains(pt);
if(b) {
nOption = (int)OHO_Point;
nSubIndex = i;
return true;
}
}
// 线
for(int i = 0; i < pts.count(); i++) {
int n1 = i;
int n2 = (i == pts.count() - 1 ? 0 : i + 1);
if(_isNearLine(pt, pts[n1], pts[n2], 1.f * 2)) {
// 判断当前线是否已经存在
if(m_oHitOption == OHO_Bound && m_pTool->isLeftDown()) {
// 添加新节点
pts.insert(i + 1, pt);
m_vecPoints.clear();
m_vecPoints = getValueOf(pts);
nOption = (int)OHO_Point;
nSubIndex = i + 1;
return true;
}
nOption = (int)OHO_Bound;
nSubIndex = i;
return true;
}
}
nOption = (int)OHO_None;
nSubIndex = -1;
return false;
}
bool nmObjLineCrack::runMove(const QPointF& pt1,
const QPointF& pt2)
{
if(isLockPos()) {
return false;
}
if(NULL == m_pAxisX || NULL == m_pAxisY) {
return false;
}
int nCount = m_vecPoints.count();
QVector<QPointF> vecPts = getPosOf(m_vecPoints); // 屏幕值
if(m_oHitOption == OHO_Point && m_nHitIndex >= 0) {
// 如果是点,不用计算偏移量,直接将该点移动到鼠标抬起的位置即可
vecPts[m_nHitIndex] = pt2;
nmDataAnalyzeManager::getCurrentInstance()->notifyDataChanged();
return moveToPos(vecPts);
} else if(m_oHitOption == OHO_Bound && m_nHitIndex >= 0) {
for(int i = 0; i < nCount; i++) {
vecPts[i] = offsetPoint(vecPts[i], pt1, pt2);
}
m_dOffsetX = pt2.x() - pt1.x();
m_dOffsetY = pt2.y() - pt1.y();
nmDataAnalyzeManager::getCurrentInstance()->notifyDataChanged();
return moveToPos(vecPts);
} else {
return false;
}
return true;
}
void nmObjLineCrack::paintBack(QPainter* painter, const ZxPaintParam& param)
{
if(NULL == m_pAxisX || NULL == m_pAxisY || \
m_pAxisX->getRangeMin() == m_pAxisX->getRangeMax() || \
m_pAxisY->getRangeMin() == m_pAxisY->getRangeMax()) {
return;
}
painter->save();
QVector<QPointF> pts = getPosOf(m_vecPoints);
// 动态更新裂缝基础数据
if(m_fractureData != nullptr) {
m_fractureData->setFractureName(m_sName);
m_fractureData->setFracturePoints(m_vecPoints);
}
// 不选中的状态
if(!pts.empty()) {
QPen pen = m_oPen;
painter->setPen(pen);
for(int i = 0; i < pts.count() - 1; i++) {
painter->drawLine(pts[i], pts[i + 1]);
}
//将名称置于中间线段下方
QFont ft = qApp->font();
ft.setPointSize(8);
painter->setFont(ft);
painter->setPen(Qt::black);
int nSegments = pts.count() - 1;
int middleIndex = (nSegments - 1) / 2;
QPointF startPoint = pts[middleIndex];
QPointF endPoint = pts[middleIndex + 1];
// 计算中点坐标
QPointF middlePoint((startPoint.x() + endPoint.x()) / 2,
(startPoint.y() + endPoint.y()) / 2);
// 计算线段的方向角度
double dx = endPoint.x() - startPoint.x();
double dy = endPoint.y() - startPoint.y();
double angle = qAtan2(dy, dx) * 180.0 / M_PI;
// 偏移距离
double offsetDistance = -3.0;
// 线段长度
double length = std::sqrt(dx * dx + dy * dy);
// 计算一个垂直于线段方向的单位向量:
QPointF offset(0, 0);
if(length > 0) {
// 选用 (dy, -dx) 作为垂直方向,正负号可根据想要的偏移朝向做调整
offset = QPointF(offsetDistance * (dy / length),
offsetDistance * (-dx / length));
}
// 最终文字基准点:在原中点的基础上加上垂直方向的偏移
QPointF textPos = middlePoint + offset;
painter->save();
painter->translate(textPos);
painter->rotate(angle);
QRectF textRect(-50, -10, 100, 20);
ZxDrawHelper::drawText(painter,
textRect,
Qt::AlignCenter | Qt::AlignVCenter,
m_sName);
painter->restore();
}
if(isSelected()) { //选中状态下
for(int i = 0; i < pts.count(); i++) {
float w = 2.2f;
QPointF pt = pts[i];
QRectF rect(pt.x() - w * 0.5f, pt.y() - w * 0.5f, w, w);
if(m_nHitIndex == i && m_oHitOption == OHO_Point) { // 填充节点
QBrush br(Qt::red);
painter->fillRect(rect, br);
} else {
painter->setPen(QColor(0, 0, 128));
painter->drawRect(rect);
}
// 击中线
if(m_nHitIndex == i && m_oHitOption == OHO_Bound) {
nmDataLogFile::getInstance()->writeLog("select line " + QString::number(i));
QPen pen(Qt::DashLine);
//pen.setWidth(1); // 设置线条宽度
// pen.setColor(Qt::green); // 设置线条颜色
painter->setPen(pen);
for(int i = 0; i < pts.count() - 1; i++) {
painter->drawLine(pts[i], pts[i + 1]);
}
}
}
}
painter->restore();
}
int nmObjLineCrack::getCrackFlowModel()
{
if(m_fractureData->getFractureFlowModel().getValue() == tr("Infinite Conductivity"))
return 0;
else
return 1;
}
void nmObjLineCrack::setCrackFlowModel(int newCrackFlowModel)
{
nmDataAttribute tempAttr = m_fractureData->getFractureFlowModel();
if(newCrackFlowModel == 0) {
tempAttr.setValue(tr("Infinite Conductivity"));
} else {
tempAttr.setValue(tr("Finite Conductivity"));
}
m_fractureData->setFractureFlowModel(tempAttr);
}
double nmObjLineCrack::getCrackDfc()
{
return m_fractureData->getFractureDfc().getValue().toDouble();
}
void nmObjLineCrack::setCrackDfc(double newCrackDfc)
{
// 从Data中取数据
nmDataAttribute tempAttr = m_fractureData->getFractureDfc();
tempAttr.setValue(newCrackDfc);
m_fractureData->setFractureDfc(tempAttr);
}
double nmObjLineCrack::getCrackDw()
{
return m_fractureData->getFractureDw().getValue().toDouble();
}
void nmObjLineCrack::setCrackDw(double newCrackDw)
{
// 从Data中取数据
nmDataAttribute tempAttr = m_fractureData->getFractureDw();
tempAttr.setValue(newCrackDw);
m_fractureData->setFractureDw(tempAttr);
}
void nmObjLineCrack::onSerialize(ZxSerializer* ser)
{
nmObjBase::onSerialize(ser);
int flowModel;
if(m_fractureData->getFractureFlowModel().getValue() == tr("Infinite Conductivity"))
flowModel = 0;
else
flowModel = 1;
ser->write("FlowModel", flowModel);
ser->write("dFc", m_fractureData->getFractureDfc().getValue().toDouble());
ser->write("dW", m_fractureData->getFractureDw().getValue().toDouble());
}
void nmObjLineCrack::onDeserialize(ZxSerializer* ser)
{
nmObjBase::onDeserialize(ser);
int flowModel;
double fractureDfc;
double fractureDw;
ser->read("FlowModel", flowModel);
ser->read("dFc", fractureDfc);
ser->read("dW", fractureDw);
this->setCrackFlowModel(flowModel);
this->setCrackDfc(fractureDfc);
this->setCrackDw(fractureDw);
}
void nmObjLineCrack::onSaveTempl(ZxSerializer* ser)
{
nmObjBase::onSaveTempl(ser);
int flowModel;
if(m_fractureData->getFractureFlowModel().getValue() == tr("Infinite Conductivity"))
flowModel = 0;
else
flowModel = 1;
ser->write("FlowModel", flowModel);
ser->write("dFc", m_fractureData->getFractureDfc().getValue().toDouble());
ser->write("dW", m_fractureData->getFractureDw().getValue().toDouble());
}
void nmObjLineCrack::onLoadTempl(ZxSerializer* ser)
{
nmObjBase::onLoadTempl(ser);
int flowModel;
double fractureDfc;
double fractureDw;
ser->read("FlowModel", flowModel);
ser->read("dFc", fractureDfc);
ser->read("dW", fractureDw);
this->setCrackFlowModel(flowModel);
this->setCrackDfc(fractureDfc);
this->setCrackDw(fractureDw);
}
void nmObjLineCrack::fillPtyPano(IxPtyPano* sheet)
{
nmObjBase::fillPtyPano(sheet);
IxPtyItem* pProp = ZX_PROP("ObjLineFracture.FlowModel", getCrackFlowModel, setCrackFlowModel);
if(NULL != pProp) {
QStringList listTags;
listTags << tr("Infinite Conductivity") << tr("Finite Conductivity");
QList<QVariant> listIndexes;
listIndexes << 0 << 1;
pProp->getPtyPano();
pProp->setOptions(listTags, listIndexes);
}
ZX_PROP("ObjLineFracture.dFc", getCrackDfc, setCrackDfc);
ZX_PROP("ObjLineFracture.dW", getCrackDw, setCrackDw);
// 裂缝起点位置
ZX_PROP("ObjLineCrackStartPos.StartPointX", getStartX, setStartX);
ZX_PROP("ObjLineCrackStartPos.StartPointY", getStartY, setStartY);
// 裂缝终点位置
ZX_PROP("ObjLineCrackEndPos.EndPointX", getEndX, setEndX);
ZX_PROP("ObjLineCrackEndPos.EndPointY", getEndY, setEndY);
}
void nmObjLineCrack::setFractureData(nmDataFracture* newFractureData)
{
m_fractureData = newFractureData;
}
nmDataFracture* nmObjLineCrack::getFractureData() const
{
return m_fractureData;
}
void nmObjLineCrack::afterCreated()
{
m_fractureData = nmDataAnalyzeManager::getCurrentInstance()->createFracture();
m_fractureData->setFractureName(m_sName);
m_fractureData->setFracturePoints(m_vecPoints);
nmDataAnalyzeManager::getCurrentInstance()->notifyDataChanged();
}
void nmObjLineCrack::removeData()
{
if(m_fractureData) {
// 从数据中心移除该数据
nmDataAnalyzeManager::getCurrentInstance()->removeFractureData(m_fractureData);
m_fractureData = nullptr;
}
}
double nmObjLineCrack::getStartX()
{
return m_fractureData->getFracturePoints().first().x();
}
void nmObjLineCrack::setStartX(double newValue)
{
m_vecPoints.first().setX(newValue);
nmDataAnalyzeManager::getCurrentInstance()->notifyDataChanged();
}
double nmObjLineCrack::getStartY()
{
return m_fractureData->getFracturePoints().first().y();
}
void nmObjLineCrack::setStartY(double newValue)
{
m_vecPoints.first().setY(newValue);
nmDataAnalyzeManager::getCurrentInstance()->notifyDataChanged();
}
double nmObjLineCrack::getEndX()
{
return m_fractureData->getFracturePoints().last().x();
}
void nmObjLineCrack::setEndX(double newValue)
{
m_vecPoints.last().setX(newValue);
nmDataAnalyzeManager::getCurrentInstance()->notifyDataChanged();
}
double nmObjLineCrack::getEndY()
{
return m_fractureData->getFracturePoints().last().y();
}
void nmObjLineCrack::setEndY(double newValue)
{
m_vecPoints.last().setY(newValue);
nmDataAnalyzeManager::getCurrentInstance()->notifyDataChanged();
}
void nmObjLineCrack::setLockForDFN()
{
setLockPos(true);
setLockSize(true);
setReadOnly(true);
}
void nmObjLineCrack::onObjVisibleChanged(bool bIsVisible)
{
if(m_fractureData != nullptr) {
m_fractureData->setPlotVisible(bIsVisible);
}
}