#include #include #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() { // 裂缝数据由DataManager统一释放,图元只保存引用。 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 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 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 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 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); } }