#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 "nmPlotGraphicBinder.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() { } 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_sFlowModel = tr("Infinite Conductivity"); m_dDfc = 0; m_dDw = 0; m_pGraphicBinder = nullptr; loadTempl(); } 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; // 点集变更 emit sigPointsChanged(); 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; bool bRet = moveToPos(vecPts); // 移动后通知点集变更 emit sigPointsChanged(); return bRet; } 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(); bool bRet = moveToPos(vecPts); // 移动后通知点集变更 emit sigPointsChanged(); return bRet; } 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(!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_sFlowModel == tr("Infinite Conductivity")) return 0; else return 1; } void nmObjLineCrack::setCrackFlowModel(int newCrackFlowModel) { if(newCrackFlowModel == 0) { m_sFlowModel = tr("Infinite Conductivity"); } else { m_sFlowModel = tr("Finite Conductivity"); } emit sigFlowModelChanged(newCrackFlowModel); } double nmObjLineCrack::getCrackDfc() { return m_dDfc; } void nmObjLineCrack::setCrackDfc(double newCrackDfc) { m_dDfc = newCrackDfc; emit sigDfcChanged(newCrackDfc); } double nmObjLineCrack::getCrackDw() { return m_dDw; } void nmObjLineCrack::setCrackDw(double newCrackDw) { m_dDw = newCrackDw; emit sigDwChanged(newCrackDw); } void nmObjLineCrack::onSerialize(ZxSerializer* ser) { nmObjBase::onSerialize(ser); int flowModel = getCrackFlowModel(); ser->write("FlowModel", flowModel); ser->write("dFc", m_dDfc); ser->write("dW", m_dDw); } 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 = getCrackFlowModel(); ser->write("FlowModel", flowModel); ser->write("dFc", m_dDfc); ser->write("dW", m_dDw); } 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); } nmDataFracture* nmObjLineCrack::getFractureData() const { if(m_pGraphicBinder) { return m_pGraphicBinder->getCrackDataFor(const_cast(this)); } return nullptr; } double nmObjLineCrack::getStartX() { if(!m_vecPoints.isEmpty()) return m_vecPoints.first().x(); return 0; } void nmObjLineCrack::setStartX(double newValue) { if(!m_vecPoints.isEmpty()) { m_vecPoints.first().setX(newValue); emit sigPointsChanged(); } } double nmObjLineCrack::getStartY() { if(!m_vecPoints.isEmpty()) return m_vecPoints.first().y(); return 0; } void nmObjLineCrack::setStartY(double newValue) { if(!m_vecPoints.isEmpty()) { m_vecPoints.first().setY(newValue); emit sigPointsChanged(); } } double nmObjLineCrack::getEndX() { if(!m_vecPoints.isEmpty()) return m_vecPoints.last().x(); return 0; } void nmObjLineCrack::setEndX(double newValue) { if(!m_vecPoints.isEmpty()) { m_vecPoints.last().setX(newValue); emit sigPointsChanged(); } } double nmObjLineCrack::getEndY() { if(!m_vecPoints.isEmpty()) return m_vecPoints.last().y(); return 0; } void nmObjLineCrack::setEndY(double newValue) { if(!m_vecPoints.isEmpty()) { m_vecPoints.last().setY(newValue); emit sigPointsChanged(); } } void nmObjLineCrack::setLockForDFN() { setLockPos(true); setLockSize(true); setReadOnly(true); }