2026-01-04 16:54:55 +08:00
|
|
|
|
#include <math.h>
|
|
|
|
|
|
#include <QDebug>
|
2026-04-23 09:10:28 +08:00
|
|
|
|
#include <QMouseEvent>
|
|
|
|
|
|
#include <QContextMenuEvent>
|
|
|
|
|
|
#include <QMenu>
|
|
|
|
|
|
#include <QAction>
|
|
|
|
|
|
#include <QMessageBox>
|
|
|
|
|
|
#include <QMap>
|
|
|
|
|
|
#include <QTimer>
|
|
|
|
|
|
#include <algorithm>
|
2026-01-06 16:03:55 +08:00
|
|
|
|
#include "MemRdWt.h"
|
2026-01-04 16:54:55 +08:00
|
|
|
|
#include "PickFrac.h"
|
2026-04-23 09:10:28 +08:00
|
|
|
|
#include "qmycustomplot.h"
|
2026-01-04 16:54:55 +08:00
|
|
|
|
#include "geometryutils.h"
|
|
|
|
|
|
|
2026-04-23 09:10:28 +08:00
|
|
|
|
// ==================== CPickFrac 实现 ====================
|
2026-01-04 16:54:55 +08:00
|
|
|
|
CPickFrac::CPickFrac(QMyCustomPlot *myCustomPlot, QString strSlfName, QString csCurve, int iMyWidth)
|
2026-04-23 09:10:28 +08:00
|
|
|
|
: m_myCustomPlot(myCustomPlot), m_iMyWidth(iMyWidth)
|
2026-01-04 16:54:55 +08:00
|
|
|
|
{
|
2026-04-23 09:10:28 +08:00
|
|
|
|
m_currentSlfName = strSlfName;
|
|
|
|
|
|
m_currentTableName = csCurve.isEmpty() ? "Frac_Hole.Table" : csCurve;
|
2026-01-04 16:54:55 +08:00
|
|
|
|
ReadFracDef();
|
2026-04-23 09:10:28 +08:00
|
|
|
|
for (int i = 0; i < iFracType2; i++) m_bTypeDraw[i] = true;
|
2026-03-27 09:47:58 +08:00
|
|
|
|
myCustomPlot->m_bDrawCore_PHYSICS = true;
|
2026-01-04 16:54:55 +08:00
|
|
|
|
ReadData(strSlfName, csCurve);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-23 09:10:28 +08:00
|
|
|
|
CPickFrac::~CPickFrac()
|
2026-01-04 16:54:55 +08:00
|
|
|
|
{
|
2026-04-23 09:10:28 +08:00
|
|
|
|
qDeleteAll(m_items);
|
2026-01-04 16:54:55 +08:00
|
|
|
|
m_FracDef.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-23 09:10:28 +08:00
|
|
|
|
void CPickFrac::setDraggingEnabled(bool enabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_draggingEnabled = enabled;
|
|
|
|
|
|
if (!enabled) {
|
|
|
|
|
|
for (auto item : m_items) item->deactivate();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-04 16:54:55 +08:00
|
|
|
|
void CPickFrac::ReadFracDef()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_FracDef.clear();
|
|
|
|
|
|
QString fracFilePath = GetConfPath() + "FRAC.CFG";
|
|
|
|
|
|
FRAC_DEF_Crack fd;
|
2026-04-23 09:10:28 +08:00
|
|
|
|
char str[512], name[512];
|
|
|
|
|
|
int r, g, b;
|
|
|
|
|
|
FILE *fp = fopen(fracFilePath.toStdString().c_str(), "r");
|
|
|
|
|
|
if (fp) {
|
|
|
|
|
|
fgets(str, 256, fp);
|
|
|
|
|
|
while (!feof(fp)) {
|
|
|
|
|
|
fgets(str, 256, fp);
|
|
|
|
|
|
QString qs = str;
|
2026-01-04 16:54:55 +08:00
|
|
|
|
qs.trimmed();
|
2026-04-23 09:10:28 +08:00
|
|
|
|
if (qs.length() < 8) break;
|
|
|
|
|
|
sscanf(str, "%d %s %d %d %d %d %d", &fd.iCode, name, &fd.iType, &r, &g, &b, &fd.nLineWidth);
|
|
|
|
|
|
fd.crColor = QColor(r, g, b);
|
2026-04-23 16:42:00 +08:00
|
|
|
|
fd.csName = QString::fromLocal8Bit(name);
|
2026-04-23 09:10:28 +08:00
|
|
|
|
fd.csName = fd.csName.trimmed();
|
2026-01-04 16:54:55 +08:00
|
|
|
|
fd.bDraw = 0;
|
|
|
|
|
|
m_FracDef.append(fd);
|
2026-04-23 09:10:28 +08:00
|
|
|
|
if (feof(fp)) break;
|
2026-01-04 16:54:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
fclose(fp);
|
2026-04-23 09:10:28 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
sprintf(name, "打开裂缝参数配置文件错误:%s!", str);
|
2026-01-06 16:03:55 +08:00
|
|
|
|
QMessageBox::information(nullptr, "读取文件失败", name);
|
2026-01-04 16:54:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CPickFrac::ReadData(QString strSlfName, QString csCurve)
|
|
|
|
|
|
{
|
2026-04-23 09:10:28 +08:00
|
|
|
|
if (strSlfName.isEmpty()) return;
|
|
|
|
|
|
if (csCurve == "AC" || csCurve.isEmpty()) csCurve = "Frac_Hole.Table";
|
|
|
|
|
|
|
|
|
|
|
|
CMemRdWt mrw;
|
|
|
|
|
|
if (!mrw.Open(strSlfName.toStdString().c_str())) return;
|
|
|
|
|
|
|
|
|
|
|
|
int iIndex = mrw.OpenTable(csCurve.toStdString().c_str());
|
|
|
|
|
|
if (iIndex < 0) { mrw.Close(); return; }
|
|
|
|
|
|
|
|
|
|
|
|
int nField = mrw.GetTableFieldCount(iIndex);
|
|
|
|
|
|
int nCount = mrw.GetTableRecordCount(iIndex);
|
|
|
|
|
|
for (int i = 0; i < nCount; ++i) {
|
|
|
|
|
|
FRAC_TABLE_Crack frac;
|
|
|
|
|
|
if (nField == 7) {
|
|
|
|
|
|
FRAC_TABLE_OLD_Crack fracold;
|
|
|
|
|
|
mrw.ReadTable(iIndex, i+1, &fracold);
|
|
|
|
|
|
frac.AorX = fracold.AorX;
|
|
|
|
|
|
frac.DEP = fracold.DEP;
|
|
|
|
|
|
frac.DIPorS = fracold.DIPorS;
|
|
|
|
|
|
frac.DIR = fracold.DIR;
|
|
|
|
|
|
frac.W = fracold.W;
|
|
|
|
|
|
frac.ID = fracold.ID;
|
|
|
|
|
|
frac.XETAorH = fracold.XETAorH;
|
|
|
|
|
|
frac.NUM = 0;
|
|
|
|
|
|
for (int j=0; j<16; ++j) frac.point[j].x = frac.point[j].y = 0;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
mrw.ReadTable(iIndex, i+1, &frac);
|
|
|
|
|
|
}
|
2026-01-04 16:54:55 +08:00
|
|
|
|
|
2026-04-23 09:10:28 +08:00
|
|
|
|
for (int j=0; j<m_FracDef.count(); ++j) {
|
|
|
|
|
|
if (m_FracDef[j].iCode == frac.ID) {
|
2026-04-23 16:42:00 +08:00
|
|
|
|
drawOne(frac, m_FracDef[j].iType, m_FracDef[j].nLineWidth, m_FracDef[j].crColor, m_FracDef[j].csName);
|
2026-04-23 09:10:28 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-04 16:54:55 +08:00
|
|
|
|
}
|
2026-04-23 09:10:28 +08:00
|
|
|
|
mrw.CloseTable(iIndex);
|
|
|
|
|
|
mrw.Close();
|
|
|
|
|
|
}
|
2026-01-04 16:54:55 +08:00
|
|
|
|
|
2026-04-23 16:42:00 +08:00
|
|
|
|
void CPickFrac::drawOne(FRAC_TABLE_Crack frac, int iType, int nLineWidth, QColor crColor, QString csName)
|
2026-04-23 09:10:28 +08:00
|
|
|
|
{
|
|
|
|
|
|
qDebug() << "========== READ FRAC ==========";
|
|
|
|
|
|
qDebug() << "DEP:" << frac.DEP << "AorX:" << frac.AorX << "XETAorH:" << frac.XETAorH
|
|
|
|
|
|
<< "ID:" << frac.ID << "iType:" << iType;
|
|
|
|
|
|
|
|
|
|
|
|
DraggableCrackItem::Type type;
|
|
|
|
|
|
if (iType == 1) type = DraggableCrackItem::TypeA_Sine;
|
|
|
|
|
|
else if (iType == 2) type = DraggableCrackItem::TypeB_Polyline;
|
|
|
|
|
|
else if (iType == 3) type = DraggableCrackItem::TypeC_Closed;
|
|
|
|
|
|
else return;
|
|
|
|
|
|
|
|
|
|
|
|
DraggableCrackItem *item = new DraggableCrackItem(m_myCustomPlot, type, crColor, nLineWidth);
|
|
|
|
|
|
item->setCrackCode(frac.ID);
|
2026-04-23 16:42:00 +08:00
|
|
|
|
item->csName = csName;
|
|
|
|
|
|
item->DIPorS = frac.DIPorS;
|
|
|
|
|
|
item->DIR = frac.DIR;
|
|
|
|
|
|
item->setLabelInfo(csName, frac.DIPorS, frac.DIR);
|
2026-04-23 09:10:28 +08:00
|
|
|
|
connect(item, &DraggableCrackItem::dataChanged, this, &CPickFrac::saveToFile);
|
|
|
|
|
|
connect(item, &DraggableCrackItem::removeMe, this, &CPickFrac::onRemoveCrackItem);
|
|
|
|
|
|
m_items.append(item);
|
|
|
|
|
|
|
|
|
|
|
|
if (iType == 1) {
|
|
|
|
|
|
double h = frac.AorX / 2.0;
|
|
|
|
|
|
double oy = -(frac.DEP + h);
|
|
|
|
|
|
double xScale = 360.0 / m_iMyWidth;
|
|
|
|
|
|
double endX = 360.0 / xScale;
|
|
|
|
|
|
item->setSineData(oy, h, frac.XETAorH, xScale, endX);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (iType == 2) {
|
|
|
|
|
|
QVector<QPointF> points;
|
|
|
|
|
|
int n = frac.NUM;
|
|
|
|
|
|
for (int j=0; j<n; ++j) {
|
|
|
|
|
|
points.append(QPointF(frac.point[j].x / 8.0, -frac.point[j].y));
|
|
|
|
|
|
}
|
|
|
|
|
|
item->setPolylineData(points);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (iType == 3) {
|
|
|
|
|
|
QVector<QPointF> points;
|
|
|
|
|
|
int n = frac.NUM;
|
|
|
|
|
|
for (int j=0; j<n; ++j) {
|
|
|
|
|
|
points.append(QPointF(frac.point[j].x / 8.0, -frac.point[j].y));
|
|
|
|
|
|
}
|
|
|
|
|
|
item->setClosedData(points);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CPickFrac::eventFilter(QObject *watched, QEvent *event)
|
|
|
|
|
|
{
|
|
|
|
|
|
return QObject::eventFilter(watched, event);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CPickFrac::saveToFile()
|
|
|
|
|
|
{
|
|
|
|
|
|
static bool isRunning = false;
|
|
|
|
|
|
if (isRunning) return false;
|
|
|
|
|
|
if (m_currentSlfName.isEmpty()) return false;
|
|
|
|
|
|
isRunning = true;
|
|
|
|
|
|
|
|
|
|
|
|
CMemRdWt *logio = new CMemRdWt();
|
|
|
|
|
|
if (!logio->Open(m_currentSlfName.toStdString().c_str(), CSlfIO::modeReadWrite)) {
|
|
|
|
|
|
delete logio;
|
|
|
|
|
|
QMessageBox::information(nullptr, "提示", "SLF文件打开失败,请检查!", QMessageBox::Yes);
|
|
|
|
|
|
isRunning = false;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString tableName = m_currentTableName;
|
|
|
|
|
|
int iIndex = logio->OpenTable(tableName.toStdString().c_str());
|
|
|
|
|
|
if (iIndex < 0) {
|
|
|
|
|
|
delete logio;
|
|
|
|
|
|
QMessageBox::information(nullptr, "提示", QString("裂缝表 %1 不存在,无法保存!").arg(tableName), QMessageBox::Yes);
|
|
|
|
|
|
isRunning = false;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-23 09:38:17 +08:00
|
|
|
|
// 如果没有裂缝,清空表记录
|
2026-04-23 09:10:28 +08:00
|
|
|
|
if (m_items.isEmpty()) {
|
|
|
|
|
|
logio->SetTableRecordCount(iIndex, 0);
|
|
|
|
|
|
logio->CloseTable(iIndex);
|
|
|
|
|
|
delete logio;
|
|
|
|
|
|
isRunning = false;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-23 09:38:17 +08:00
|
|
|
|
// 按深度排序
|
2026-04-23 09:10:28 +08:00
|
|
|
|
QMap<double, DraggableCrackItem*> sortedMap;
|
|
|
|
|
|
for (DraggableCrackItem *item : m_items) {
|
|
|
|
|
|
double depth = item->getDepthForSort();
|
|
|
|
|
|
sortedMap[depth] = item;
|
|
|
|
|
|
}
|
|
|
|
|
|
logio->SetTableRecordCount(iIndex, sortedMap.size());
|
|
|
|
|
|
|
|
|
|
|
|
int recordIndex = 1;
|
|
|
|
|
|
for (auto it = sortedMap.begin(); it != sortedMap.end(); ++it) {
|
|
|
|
|
|
FRAC_TABLE_Crack fracData;
|
|
|
|
|
|
it.value()->getCurrentFracData(fracData);
|
|
|
|
|
|
logio->WriteTable(iIndex, recordIndex, &fracData);
|
|
|
|
|
|
recordIndex++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
logio->CloseTable(iIndex);
|
|
|
|
|
|
delete logio;
|
|
|
|
|
|
isRunning = false;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CPickFrac::onRemoveCrackItem(DraggableCrackItem *item)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!item) return;
|
|
|
|
|
|
if (m_items.removeOne(item)) {
|
2026-04-23 09:38:17 +08:00
|
|
|
|
// 立即从画布移除所有图形项
|
|
|
|
|
|
item->cleanupFromPlot();
|
|
|
|
|
|
// 失活并清空静态指针
|
|
|
|
|
|
if (DraggableCrackItem::getActiveItem() == item) {
|
|
|
|
|
|
item->deactivate();
|
|
|
|
|
|
}
|
|
|
|
|
|
// 断开信号
|
2026-04-23 09:10:28 +08:00
|
|
|
|
disconnect(item, nullptr, this, nullptr);
|
2026-04-23 09:38:17 +08:00
|
|
|
|
// 直接删除,不再延迟
|
|
|
|
|
|
delete item;
|
|
|
|
|
|
// 强制重绘
|
2026-04-23 09:10:28 +08:00
|
|
|
|
m_myCustomPlot->replot();
|
2026-04-23 09:38:17 +08:00
|
|
|
|
// 保存文件
|
|
|
|
|
|
saveToFile();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::cleanupFromPlot()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_type == TypeA_Sine) {
|
|
|
|
|
|
if (m_curve) m_plot->removeItem(m_curve);
|
|
|
|
|
|
if (m_tracer1) m_plot->removeItem(m_tracer1);
|
|
|
|
|
|
if (m_tracer2) m_plot->removeItem(m_tracer2);
|
|
|
|
|
|
} else if (m_type == TypeB_Polyline) {
|
|
|
|
|
|
for (auto &item : m_lines) {
|
|
|
|
|
|
if (item.line) m_plot->removeItem(item.line);
|
|
|
|
|
|
if (item.startTracer) m_plot->removeItem(item.startTracer);
|
|
|
|
|
|
if (item.endTracer) m_plot->removeItem(item.endTracer);
|
|
|
|
|
|
}
|
|
|
|
|
|
m_lines.clear();
|
|
|
|
|
|
} else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
if (m_curveC) {
|
|
|
|
|
|
m_plot->removePlottable(m_curveC);
|
|
|
|
|
|
m_curveC = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
for (auto label : m_labelsC) {
|
|
|
|
|
|
if (label) m_plot->removeItem(label);
|
|
|
|
|
|
}
|
|
|
|
|
|
m_labelsC.clear();
|
|
|
|
|
|
m_pointsC.clear();
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-23 16:42:00 +08:00
|
|
|
|
void DraggableCrackItem::setShow(bool flag)
|
|
|
|
|
|
{
|
|
|
|
|
|
setVisible(flag);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-23 09:10:28 +08:00
|
|
|
|
// ==================== DraggableCrackItem 实现 ====================
|
|
|
|
|
|
QPointer<DraggableCrackItem> DraggableCrackItem::s_activeItem = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
DraggableCrackItem::DraggableCrackItem(QCustomPlot *plot, Type type, const QColor &color, int lineWidth)
|
|
|
|
|
|
: QObject(plot), m_plot(plot), m_type(type), m_color(color), m_lineWidth(lineWidth)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_type == TypeA_Sine) {
|
|
|
|
|
|
m_curve = new QCPItemCurve(m_plot);
|
|
|
|
|
|
m_curve->setPen(QPen(m_color, m_lineWidth));
|
|
|
|
|
|
m_curve->setLayer("overlay");
|
|
|
|
|
|
auto createTracer = [this](double x, double y) -> QCPItemTracer* {
|
|
|
|
|
|
QCPItemTracer *t = new QCPItemTracer(m_plot);
|
|
|
|
|
|
t->setStyle(QCPItemTracer::tsSquare);
|
|
|
|
|
|
t->setSize(8);
|
|
|
|
|
|
t->setPen(QPen(Qt::black, 1));
|
|
|
|
|
|
t->setBrush(QBrush(Qt::black));
|
|
|
|
|
|
t->setSelectable(true);
|
|
|
|
|
|
t->setLayer("overlay");
|
|
|
|
|
|
t->position->setCoords(x, y);
|
|
|
|
|
|
t->setVisible(false);
|
|
|
|
|
|
return t;
|
|
|
|
|
|
};
|
|
|
|
|
|
m_tracer1 = createTracer(0,0);
|
|
|
|
|
|
m_tracer2 = createTracer(0,0);
|
|
|
|
|
|
m_plot->installEventFilter(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (m_type == TypeB_Polyline) {
|
|
|
|
|
|
m_plot->installEventFilter(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
m_curveC = new QCPCurve(m_plot->xAxis, m_plot->yAxis);
|
|
|
|
|
|
m_curveC->setPen(QPen(m_color, m_lineWidth));
|
|
|
|
|
|
m_curveC->setScatterStyle(QCPScatterStyle::ssCircle);
|
|
|
|
|
|
m_curveC->setLineStyle(QCPCurve::lsLine);
|
|
|
|
|
|
m_curveC->setLayer("overlay");
|
|
|
|
|
|
m_plot->installEventFilter(this);
|
|
|
|
|
|
}
|
2026-04-23 16:42:00 +08:00
|
|
|
|
// 创建文本标签
|
|
|
|
|
|
m_labelText = new QCPItemText(m_plot);
|
|
|
|
|
|
m_labelText->setFont(QFont("微软雅黑", 7));
|
|
|
|
|
|
m_labelText->setColor(Qt::black);
|
|
|
|
|
|
m_labelText->setPositionAlignment(Qt::AlignCenter);
|
|
|
|
|
|
m_labelText->setLayer("overlay");
|
|
|
|
|
|
m_labelText->setVisible(false);
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DraggableCrackItem::~DraggableCrackItem()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_type == TypeA_Sine) {
|
|
|
|
|
|
if (m_tracer1) m_plot->removeItem(m_tracer1);
|
|
|
|
|
|
if (m_tracer2) m_plot->removeItem(m_tracer2);
|
|
|
|
|
|
if (m_curve) m_plot->removeItem(m_curve);
|
|
|
|
|
|
} else if (m_type == TypeB_Polyline) {
|
|
|
|
|
|
clearLines();
|
|
|
|
|
|
} else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
clearPolylineC();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (s_activeItem == this) s_activeItem = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-23 16:42:00 +08:00
|
|
|
|
void DraggableCrackItem::setLabelInfo(const QString &name, double angle, double angle2, int digitCapacity)
|
|
|
|
|
|
{
|
|
|
|
|
|
QString text = name;
|
|
|
|
|
|
if (angle >= 0) {
|
|
|
|
|
|
text += QString(" %1").arg(angle, 0, 'f', digitCapacity) + "-" + QString("%1").arg(angle2, 0, 'f', digitCapacity);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (m_labelText) {
|
|
|
|
|
|
m_labelText->setText(text);
|
|
|
|
|
|
}
|
|
|
|
|
|
updateLabelPosition();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::updateLabelPosition()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_labelText) return;
|
|
|
|
|
|
QPointF pos;
|
|
|
|
|
|
if (m_type == TypeA_Sine) {
|
|
|
|
|
|
// 曲线中心点(起点和终点的中点)
|
|
|
|
|
|
double centerX = (m_orig_startX + m_orig_endX) / 2.0 + m_offsetXA;
|
|
|
|
|
|
double centerY = m_depth + m_offsetYA;
|
|
|
|
|
|
pos = QPointF(centerX, centerY);
|
|
|
|
|
|
} else if (m_type == TypeB_Polyline) {
|
|
|
|
|
|
if (!m_lines.isEmpty()) {
|
|
|
|
|
|
// 取第一条线段的中点
|
|
|
|
|
|
QPointF p1 = m_lines.first().startOrig + QPointF(m_offsetXB, m_offsetYB);
|
|
|
|
|
|
QPointF p2 = m_lines.first().endOrig + QPointF(m_offsetXB, m_offsetYB);
|
|
|
|
|
|
pos = (p1 + p2) / 2.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
if (!m_pointsC.isEmpty()) {
|
|
|
|
|
|
// 取第一个点
|
|
|
|
|
|
pos = m_pointsC.first() + QPointF(m_offsetXC, m_offsetYC);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
m_labelText->position->setCoords(pos.x(), pos.y());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-23 09:10:28 +08:00
|
|
|
|
void DraggableCrackItem::setVisible(bool visible)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_pendingDelete) return;
|
|
|
|
|
|
if (m_type == TypeA_Sine) {
|
|
|
|
|
|
if (m_curve) m_curve->setVisible(visible);
|
|
|
|
|
|
if (m_tracer1) m_tracer1->setVisible(visible && (s_activeItem == this));
|
|
|
|
|
|
if (m_tracer2) m_tracer2->setVisible(visible && (s_activeItem == this));
|
|
|
|
|
|
} else if (m_type == TypeB_Polyline) {
|
|
|
|
|
|
for (auto &item : m_lines) {
|
|
|
|
|
|
if (item.line) item.line->setVisible(visible);
|
|
|
|
|
|
bool show = visible && (s_activeItem == this);
|
|
|
|
|
|
if (item.startTracer) item.startTracer->setVisible(show);
|
|
|
|
|
|
if (item.endTracer) item.endTracer->setVisible(show);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
if (m_curveC) m_curveC->setVisible(visible);
|
|
|
|
|
|
bool show = visible && (s_activeItem == this);
|
|
|
|
|
|
for (auto label : m_labelsC) label->setVisible(show);
|
|
|
|
|
|
}
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::deactivate()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_type == TypeA_Sine) {
|
|
|
|
|
|
setTracerHighlight(m_tracer1, false);
|
|
|
|
|
|
setTracerHighlight(m_tracer2, false);
|
|
|
|
|
|
m_dragStateA = IdleA;
|
|
|
|
|
|
setDragPointsVisible(false);
|
|
|
|
|
|
} else if (m_type == TypeB_Polyline) {
|
|
|
|
|
|
m_dragStateB = IdleB;
|
|
|
|
|
|
m_draggedLineIndex = -1;
|
|
|
|
|
|
setDragPointsVisible(false);
|
|
|
|
|
|
} else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
m_cDragging = false;
|
|
|
|
|
|
m_draggingPoint = false;
|
|
|
|
|
|
m_draggedPointIndex = -1;
|
|
|
|
|
|
setDragPointsVisible(false);
|
|
|
|
|
|
}
|
2026-04-23 09:38:17 +08:00
|
|
|
|
if (s_activeItem == this) {
|
|
|
|
|
|
s_activeItem = nullptr;
|
|
|
|
|
|
}
|
2026-04-23 09:10:28 +08:00
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::setDragPointsVisible(bool visible)
|
|
|
|
|
|
{
|
2026-04-23 09:38:17 +08:00
|
|
|
|
if (m_pendingDelete) return;
|
2026-04-23 09:10:28 +08:00
|
|
|
|
if (m_type == TypeA_Sine) {
|
|
|
|
|
|
if (m_tracer1) m_tracer1->setVisible(visible);
|
|
|
|
|
|
if (m_tracer2) m_tracer2->setVisible(visible);
|
|
|
|
|
|
} else if (m_type == TypeB_Polyline) {
|
|
|
|
|
|
for (auto &item : m_lines) {
|
|
|
|
|
|
if (item.startTracer) item.startTracer->setVisible(visible);
|
|
|
|
|
|
if (item.endTracer) item.endTracer->setVisible(visible);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
for (auto label : m_labelsC) {
|
|
|
|
|
|
if (label) label->setVisible(visible);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::startEditing()
|
|
|
|
|
|
{
|
2026-04-23 09:38:17 +08:00
|
|
|
|
if (m_pendingDelete) return;
|
2026-04-23 09:10:28 +08:00
|
|
|
|
m_editingMode = true;
|
|
|
|
|
|
if (s_activeItem && s_activeItem != this) s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = this;
|
|
|
|
|
|
setDragPointsVisible(true);
|
|
|
|
|
|
if (m_type == TypeB_Polyline) {
|
|
|
|
|
|
clearLines();
|
|
|
|
|
|
m_isAddingLine = false;
|
|
|
|
|
|
} else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
clearPolylineC();
|
|
|
|
|
|
m_cFinished = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::finishEditing()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_editingMode) return;
|
|
|
|
|
|
m_editingMode = false;
|
|
|
|
|
|
if (s_activeItem == this) {
|
|
|
|
|
|
deactivate();
|
|
|
|
|
|
}
|
|
|
|
|
|
emit dataChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------- 模式A ----------
|
|
|
|
|
|
void DraggableCrackItem::setSineData(double depth, double amplitude, double phase, double xScale, double width)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_depth = depth;
|
|
|
|
|
|
m_endX = width;
|
|
|
|
|
|
m_originalXETAorH = phase;
|
|
|
|
|
|
m_originalAorX = amplitude * 2.0;
|
|
|
|
|
|
m_orig_x1 = m_endX * 0.18;
|
|
|
|
|
|
m_orig_x2 = m_endX * 0.82;
|
|
|
|
|
|
m_orig_y1 = depth + amplitude;
|
|
|
|
|
|
m_orig_y2 = depth - amplitude;
|
|
|
|
|
|
m_orig_startX = 0;
|
|
|
|
|
|
m_orig_endX = m_endX;
|
|
|
|
|
|
m_orig_startDirX = m_endX * 0.3;
|
|
|
|
|
|
m_orig_endDirX = m_endX * 0.7;
|
|
|
|
|
|
updateCurveFromTargets();
|
|
|
|
|
|
updateCurvePosition();
|
|
|
|
|
|
updateTracers();
|
2026-04-23 16:42:00 +08:00
|
|
|
|
updateLabelPosition();
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::updateCurveFromTargets()
|
|
|
|
|
|
{
|
|
|
|
|
|
double t1 = m_orig_x1 / m_endX;
|
|
|
|
|
|
double t2 = m_orig_x2 / m_endX;
|
|
|
|
|
|
double u1 = 1 - t1, u2 = 1 - t2;
|
|
|
|
|
|
double P0x = 0, P0y = m_depth;
|
|
|
|
|
|
double P3x = m_endX, P3y = m_depth;
|
|
|
|
|
|
double P1x = m_orig_x1, P2x = m_orig_x2;
|
|
|
|
|
|
double a11 = 3 * u1 * u1 * t1;
|
|
|
|
|
|
double a12 = 3 * u1 * t1 * t1;
|
|
|
|
|
|
double b1 = m_orig_y1 - (u1*u1*u1 * P0y + t1*t1*t1 * P3y);
|
|
|
|
|
|
double a21 = 3 * u2 * u2 * t2;
|
|
|
|
|
|
double a22 = 3 * u2 * t2 * t2;
|
|
|
|
|
|
double b2 = m_orig_y2 - (u2*u2*u2 * P0y + t2*t2*t2 * P3y);
|
|
|
|
|
|
double det = a11 * a22 - a12 * a21;
|
|
|
|
|
|
if (fabs(det) > 1e-6) {
|
|
|
|
|
|
double P1y = (b1 * a22 - a12 * b2) / det;
|
|
|
|
|
|
double P2y = (a11 * b2 - b1 * a21) / det;
|
|
|
|
|
|
m_orig_startDirX = P1x;
|
|
|
|
|
|
m_orig_startDirY = P1y;
|
|
|
|
|
|
m_orig_endDirX = P2x;
|
|
|
|
|
|
m_orig_endDirY = P2y;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::updateCurvePosition()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_curve) return;
|
|
|
|
|
|
m_curve->start->setCoords(m_orig_startX + m_offsetXA, m_depth + m_offsetYA);
|
|
|
|
|
|
m_curve->end->setCoords(m_orig_endX + m_offsetXA, m_depth + m_offsetYA);
|
|
|
|
|
|
m_curve->startDir->setCoords(m_orig_startDirX + m_offsetXA, m_orig_startDirY + m_offsetYA);
|
|
|
|
|
|
m_curve->endDir->setCoords(m_orig_endDirX + m_offsetXA, m_orig_endDirY + m_offsetYA);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::updateTracers()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_tracer1 || !m_tracer2) return;
|
|
|
|
|
|
m_tracer1->position->setCoords(m_orig_x1 + m_offsetXA, m_orig_y1 + m_offsetYA);
|
|
|
|
|
|
m_tracer2->position->setCoords(m_orig_x2 + m_offsetXA, m_orig_y2 + m_offsetYA);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::setTracerHighlight(QCPItemTracer *tracer, bool highlight)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!tracer) return;
|
|
|
|
|
|
if (highlight) {
|
|
|
|
|
|
tracer->setPen(QPen(Qt::red, 2));
|
|
|
|
|
|
tracer->setBrush(QBrush(Qt::red));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
tracer->setPen(QPen(Qt::black, 1));
|
|
|
|
|
|
tracer->setBrush(QBrush(Qt::black));
|
|
|
|
|
|
}
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------- 模式B ----------
|
|
|
|
|
|
void DraggableCrackItem::setPolylineData(const QVector<QPointF> &points, double scaleX, double flipY)
|
|
|
|
|
|
{
|
|
|
|
|
|
clearLines();
|
|
|
|
|
|
if (points.size() < 2) return;
|
|
|
|
|
|
auto createTracer = [this](double x, double y, const QColor &color) -> QCPItemTracer* {
|
|
|
|
|
|
QCPItemTracer *t = new QCPItemTracer(m_plot);
|
|
|
|
|
|
t->setStyle(QCPItemTracer::tsSquare);
|
|
|
|
|
|
t->setSize(10);
|
|
|
|
|
|
t->setPen(QPen(Qt::black, 1));
|
|
|
|
|
|
t->setBrush(QBrush(color));
|
|
|
|
|
|
t->setSelectable(true);
|
|
|
|
|
|
t->setLayer("overlay");
|
|
|
|
|
|
t->position->setCoords(x, y);
|
|
|
|
|
|
t->setVisible(false);
|
|
|
|
|
|
return t;
|
|
|
|
|
|
};
|
|
|
|
|
|
for (int i = 0; i < points.size() - 1; ++i) {
|
|
|
|
|
|
QPointF p1 = points[i];
|
|
|
|
|
|
QPointF p2 = points[i+1];
|
|
|
|
|
|
QCPItemLine *line = new QCPItemLine(m_plot);
|
|
|
|
|
|
line->setPen(QPen(m_color, m_lineWidth));
|
|
|
|
|
|
line->setLayer("overlay");
|
|
|
|
|
|
QCPItemTracer *startTracer = createTracer(p1.x(), p1.y(), Qt::black);
|
|
|
|
|
|
QCPItemTracer *endTracer = createTracer(p2.x(), p2.y(), Qt::black);
|
|
|
|
|
|
LineItem item;
|
|
|
|
|
|
item.startOrig = p1;
|
|
|
|
|
|
item.endOrig = p2;
|
|
|
|
|
|
item.line = line;
|
|
|
|
|
|
item.startTracer = startTracer;
|
|
|
|
|
|
item.endTracer = endTracer;
|
|
|
|
|
|
m_lines.append(item);
|
2026-04-23 16:42:00 +08:00
|
|
|
|
i++;
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
updateLinesPosition();
|
2026-04-23 16:42:00 +08:00
|
|
|
|
updateLabelPosition();
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::updateLineEndpoints(LineItem &item)
|
|
|
|
|
|
{
|
|
|
|
|
|
item.startTracer->position->setCoords(item.startOrig.x() + m_offsetXB, item.startOrig.y() + m_offsetYB);
|
|
|
|
|
|
item.endTracer->position->setCoords(item.endOrig.x() + m_offsetXB, item.endOrig.y() + m_offsetYB);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::updateLinesPosition()
|
|
|
|
|
|
{
|
|
|
|
|
|
for (auto &item : m_lines) {
|
|
|
|
|
|
item.line->start->setCoords(item.startOrig.x() + m_offsetXB, item.startOrig.y() + m_offsetYB);
|
|
|
|
|
|
item.line->end->setCoords(item.endOrig.x() + m_offsetXB, item.endOrig.y() + m_offsetYB);
|
|
|
|
|
|
updateLineEndpoints(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::clearLines()
|
|
|
|
|
|
{
|
|
|
|
|
|
for (auto &item : m_lines) {
|
2026-04-23 09:38:17 +08:00
|
|
|
|
if (item.line) { m_plot->removeItem(item.line); }
|
|
|
|
|
|
if (item.startTracer) { m_plot->removeItem(item.startTracer); }
|
|
|
|
|
|
if (item.endTracer) { m_plot->removeItem(item.endTracer); }
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
m_lines.clear();
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------- 模式C ----------
|
|
|
|
|
|
void DraggableCrackItem::setClosedData(const QVector<QPointF> &points, double scaleX, double flipY)
|
|
|
|
|
|
{
|
|
|
|
|
|
clearPolylineC();
|
|
|
|
|
|
if (points.size() < 3) return;
|
|
|
|
|
|
m_pointsC = points;
|
|
|
|
|
|
for (int i = 0; i < m_pointsC.size(); ++i) {
|
|
|
|
|
|
QCPItemText *label = new QCPItemText(m_plot);
|
|
|
|
|
|
label->setText(" ");
|
|
|
|
|
|
label->setFont(QFont("Arial", 6, QFont::Bold));
|
|
|
|
|
|
label->setColor(Qt::black);
|
|
|
|
|
|
label->setBrush(QBrush(Qt::black));
|
|
|
|
|
|
label->setPen(QPen(Qt::black, 1));
|
|
|
|
|
|
label->position->setCoords(m_pointsC[i].x(), m_pointsC[i].y());
|
|
|
|
|
|
label->setPositionAlignment(Qt::AlignCenter);
|
|
|
|
|
|
label->setLayer("overlay");
|
|
|
|
|
|
label->setVisible(false);
|
|
|
|
|
|
m_labelsC.append(label);
|
|
|
|
|
|
}
|
|
|
|
|
|
m_cFinished = true;
|
|
|
|
|
|
updatePolylineC(true);
|
2026-04-23 16:42:00 +08:00
|
|
|
|
updateLabelPosition();
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::updatePolylineC(bool closed)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_curveC) return;
|
|
|
|
|
|
if (m_pointsC.isEmpty()) {
|
|
|
|
|
|
m_curveC->setData(QVector<double>(), QVector<double>());
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
QVector<double> xs, ys;
|
|
|
|
|
|
for (const auto &p : m_pointsC) {
|
|
|
|
|
|
xs << p.x() + m_offsetXC;
|
|
|
|
|
|
ys << p.y() + m_offsetYC;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (closed && m_pointsC.size() >= 3) {
|
|
|
|
|
|
xs << m_pointsC.first().x() + m_offsetXC;
|
|
|
|
|
|
ys << m_pointsC.first().y() + m_offsetYC;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_curveC->setData(xs, ys);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::clearPolylineC()
|
|
|
|
|
|
{
|
|
|
|
|
|
for (auto label : m_labelsC) {
|
|
|
|
|
|
if (label) {
|
2026-04-23 16:42:00 +08:00
|
|
|
|
if (m_plot) m_plot->removeItem(label);
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
m_labelsC.clear();
|
|
|
|
|
|
m_pointsC.clear();
|
2026-04-23 16:42:00 +08:00
|
|
|
|
// 仅当曲线对象仍然存在于 plot 中时才清空数据
|
|
|
|
|
|
if (m_curveC && m_plot && m_plot->plottableCount() > 0) {
|
|
|
|
|
|
// 检查 m_curveC 是否还在 plot 的 plottable 列表中
|
|
|
|
|
|
bool found = false;
|
|
|
|
|
|
for (int i = 0; i < m_plot->plottableCount(); ++i) {
|
|
|
|
|
|
if (m_plot->plottable(i) == m_curveC) {
|
|
|
|
|
|
found = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (found) {
|
|
|
|
|
|
m_curveC->setData(QVector<double>(), QVector<double>());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-23 09:10:28 +08:00
|
|
|
|
m_offsetXC = m_offsetYC = 0.0;
|
|
|
|
|
|
m_cFinished = false;
|
|
|
|
|
|
m_cDragging = false;
|
|
|
|
|
|
m_draggingPoint = false;
|
|
|
|
|
|
m_draggedPointIndex = -1;
|
2026-04-23 16:42:00 +08:00
|
|
|
|
if (m_plot) m_plot->replot();
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------- 保存辅助 ----------
|
|
|
|
|
|
double DraggableCrackItem::getDepthForSort() const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_type == TypeA_Sine)
|
|
|
|
|
|
return m_depth + m_offsetYA;
|
|
|
|
|
|
else if (m_type == TypeB_Polyline && !m_lines.isEmpty())
|
|
|
|
|
|
return m_lines.first().startOrig.y() + m_offsetYB;
|
|
|
|
|
|
else if (m_type == TypeC_Closed && !m_pointsC.isEmpty())
|
|
|
|
|
|
return m_pointsC.first().y() + m_offsetYC;
|
|
|
|
|
|
return 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DraggableCrackItem::getCurrentFracData(FRAC_TABLE_Crack &data) const
|
|
|
|
|
|
{
|
|
|
|
|
|
memset(&data, 0, sizeof(FRAC_TABLE_Crack));
|
|
|
|
|
|
data.ID = m_crackCode;
|
|
|
|
|
|
|
|
|
|
|
|
if (m_type == TypeA_Sine) {
|
|
|
|
|
|
double centerY = (m_orig_y1 + m_orig_y2) / 2.0 + m_offsetYA;
|
|
|
|
|
|
double halfHeight = (m_orig_y1 - m_orig_y2) / 2.0;
|
|
|
|
|
|
double savedDEP = -centerY - halfHeight;
|
|
|
|
|
|
double savedAorX = halfHeight * 2.0;
|
|
|
|
|
|
data.DEP = savedDEP;
|
|
|
|
|
|
data.AorX = savedAorX;
|
|
|
|
|
|
data.XETAorH = m_originalXETAorH;
|
|
|
|
|
|
data.NUM = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (m_type == TypeB_Polyline) {
|
|
|
|
|
|
QVector<QPointF> allPoints;
|
|
|
|
|
|
for (const LineItem &item : m_lines) {
|
|
|
|
|
|
QPointF p1 = item.startOrig + QPointF(m_offsetXB, m_offsetYB);
|
|
|
|
|
|
QPointF p2 = item.endOrig + QPointF(m_offsetXB, m_offsetYB);
|
|
|
|
|
|
allPoints.append(p1);
|
|
|
|
|
|
allPoints.append(p2);
|
|
|
|
|
|
}
|
|
|
|
|
|
QVector<QPointF> uniquePoints;
|
|
|
|
|
|
for (const QPointF &p : allPoints) {
|
|
|
|
|
|
if (uniquePoints.isEmpty() || uniquePoints.last() != p)
|
|
|
|
|
|
uniquePoints.append(p);
|
|
|
|
|
|
}
|
|
|
|
|
|
data.NUM = uniquePoints.size();
|
|
|
|
|
|
for (int i = 0; i < uniquePoints.size() && i < 16; ++i) {
|
|
|
|
|
|
data.point[i].x = uniquePoints[i].x() * 8.0f;
|
|
|
|
|
|
data.point[i].y = -uniquePoints[i].y();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (uniquePoints.size() > 0)
|
|
|
|
|
|
data.DEP = uniquePoints[0].y();
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
QVector<QPointF> finalPoints;
|
|
|
|
|
|
for (const QPointF &p : m_pointsC) {
|
|
|
|
|
|
finalPoints.append(p + QPointF(m_offsetXC, m_offsetYC));
|
|
|
|
|
|
}
|
|
|
|
|
|
data.NUM = finalPoints.size();
|
|
|
|
|
|
for (int i = 0; i < finalPoints.size() && i < 16; ++i) {
|
|
|
|
|
|
data.point[i].x = finalPoints[i].x() * 8.0f;
|
|
|
|
|
|
data.point[i].y = -finalPoints[i].y();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (finalPoints.size() > 0)
|
|
|
|
|
|
data.DEP = finalPoints[0].y();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------- 事件过滤器 ----------
|
|
|
|
|
|
bool DraggableCrackItem::eventFilter(QObject *obj, QEvent *event)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (obj != m_plot) return false;
|
|
|
|
|
|
if (m_pendingDelete) return false; // 已标记删除,忽略所有事件
|
|
|
|
|
|
|
|
|
|
|
|
// 右键菜单处理
|
|
|
|
|
|
if (event->type() == QEvent::ContextMenu) {
|
|
|
|
|
|
QContextMenuEvent *ce = static_cast<QContextMenuEvent*>(event);
|
|
|
|
|
|
if (s_activeItem == this) {
|
|
|
|
|
|
QMenu menu;
|
|
|
|
|
|
QAction *deleteAction = menu.addAction("删除裂缝");
|
|
|
|
|
|
QAction *selectedAction = menu.exec(ce->globalPos());
|
|
|
|
|
|
if (selectedAction == deleteAction) {
|
|
|
|
|
|
m_pendingDelete = true;
|
2026-04-23 09:38:17 +08:00
|
|
|
|
deactivate(); // 清空全局激活指针
|
|
|
|
|
|
emit removeMe(this); // 触发删除
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
2026-04-23 09:38:17 +08:00
|
|
|
|
return true; // 阻止事件继续传递
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QMouseEvent *me = static_cast<QMouseEvent*>(event);
|
|
|
|
|
|
|
|
|
|
|
|
if (event->type() == QEvent::MouseButtonPress && me->button() == Qt::LeftButton) {
|
|
|
|
|
|
bool shiftPressed = (me->modifiers() & Qt::ShiftModifier);
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 模式B:添加线段(Shift) =====
|
|
|
|
|
|
if (m_type == TypeB_Polyline && shiftPressed) {
|
|
|
|
|
|
if (!m_isAddingLine) {
|
|
|
|
|
|
double x = m_plot->xAxis->pixelToCoord(me->pos().x());
|
|
|
|
|
|
double y = m_plot->yAxis->pixelToCoord(me->pos().y());
|
|
|
|
|
|
m_tempPoint = QPointF(x - m_offsetXB, y - m_offsetYB);
|
|
|
|
|
|
m_isAddingLine = true;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
double x = m_plot->xAxis->pixelToCoord(me->pos().x());
|
|
|
|
|
|
double y = m_plot->yAxis->pixelToCoord(me->pos().y());
|
|
|
|
|
|
QPointF p2(x - m_offsetXB, y - m_offsetYB);
|
|
|
|
|
|
QCPItemLine *line = new QCPItemLine(m_plot);
|
|
|
|
|
|
line->setPen(QPen(m_color, m_lineWidth));
|
|
|
|
|
|
line->setLayer("overlay");
|
|
|
|
|
|
auto createTracer = [this](double x, double y, const QColor &color) -> QCPItemTracer* {
|
|
|
|
|
|
QCPItemTracer *t = new QCPItemTracer(m_plot);
|
|
|
|
|
|
t->setStyle(QCPItemTracer::tsSquare);
|
|
|
|
|
|
t->setSize(10);
|
|
|
|
|
|
t->setPen(QPen(Qt::black, 1));
|
|
|
|
|
|
t->setBrush(QBrush(color));
|
|
|
|
|
|
t->setSelectable(true);
|
|
|
|
|
|
t->setLayer("overlay");
|
|
|
|
|
|
t->position->setCoords(x + m_offsetXB, y + m_offsetYB);
|
|
|
|
|
|
t->setVisible(false);
|
|
|
|
|
|
return t;
|
|
|
|
|
|
};
|
|
|
|
|
|
QCPItemTracer *startTracer = createTracer(m_tempPoint.x(), m_tempPoint.y(), Qt::black);
|
|
|
|
|
|
QCPItemTracer *endTracer = createTracer(p2.x(), p2.y(), Qt::black);
|
|
|
|
|
|
LineItem item;
|
|
|
|
|
|
item.startOrig = m_tempPoint;
|
|
|
|
|
|
item.endOrig = p2;
|
|
|
|
|
|
item.line = line;
|
|
|
|
|
|
item.startTracer = startTracer;
|
|
|
|
|
|
item.endTracer = endTracer;
|
|
|
|
|
|
m_lines.append(item);
|
|
|
|
|
|
updateLinesPosition();
|
|
|
|
|
|
m_isAddingLine = false;
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 模式C:添加点(Shift,未完成) =====
|
|
|
|
|
|
if (m_type == TypeC_Closed && shiftPressed && !m_cFinished) {
|
|
|
|
|
|
if (s_activeItem && s_activeItem != this) s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = this;
|
|
|
|
|
|
setDragPointsVisible(true);
|
|
|
|
|
|
double x = m_plot->xAxis->pixelToCoord(me->pos().x());
|
|
|
|
|
|
double y = m_plot->yAxis->pixelToCoord(me->pos().y());
|
|
|
|
|
|
QPointF pt(x - m_offsetXC, y - m_offsetYC);
|
|
|
|
|
|
m_pointsC.append(pt);
|
|
|
|
|
|
QCPItemText *label = new QCPItemText(m_plot);
|
|
|
|
|
|
label->setText(" ");
|
|
|
|
|
|
label->setFont(QFont("Arial", 6, QFont::Bold));
|
|
|
|
|
|
label->setColor(Qt::black);
|
|
|
|
|
|
label->setBrush(QBrush(Qt::black));
|
|
|
|
|
|
label->setPen(QPen(Qt::black, 1));
|
|
|
|
|
|
label->position->setCoords(x, y);
|
|
|
|
|
|
label->setPositionAlignment(Qt::AlignCenter);
|
|
|
|
|
|
label->setLayer("overlay");
|
|
|
|
|
|
label->setVisible(true);
|
|
|
|
|
|
m_labelsC.append(label);
|
|
|
|
|
|
updatePolylineC(false);
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 模式C:完成封闭(非Shift,未完成) =====
|
|
|
|
|
|
if (m_type == TypeC_Closed && !shiftPressed && !m_cFinished) {
|
|
|
|
|
|
if (m_pointsC.size() >= 3) {
|
|
|
|
|
|
m_cFinished = true;
|
|
|
|
|
|
updatePolylineC(true);
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
if (m_editingMode) {
|
|
|
|
|
|
finishEditing();
|
2026-01-04 16:54:55 +08:00
|
|
|
|
}
|
2026-04-23 09:10:28 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
clearPolylineC();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (s_activeItem == this) {
|
|
|
|
|
|
s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 编辑模式下,模式B:非Shift左键点击空白结束编辑 =====
|
|
|
|
|
|
if (m_type == TypeB_Polyline && !shiftPressed && m_editingMode && !m_isAddingLine) {
|
|
|
|
|
|
finishEditing();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 模式A:拖拽点或曲线 =====
|
|
|
|
|
|
if (m_type == TypeA_Sine && !shiftPressed) {
|
|
|
|
|
|
QPointF pixel = me->localPos();
|
|
|
|
|
|
double d1 = m_tracer1->selectTest(pixel, false);
|
|
|
|
|
|
double d2 = m_tracer2->selectTest(pixel, false);
|
|
|
|
|
|
double curveDist = m_curve->selectTest(pixel, false);
|
|
|
|
|
|
if (d1 >= 0 && d1 < 15 || d2 >= 0 && d2 < 15 || (curveDist >= 0 && curveDist < 5)) {
|
|
|
|
|
|
if (s_activeItem && s_activeItem != this) s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = this;
|
|
|
|
|
|
setDragPointsVisible(true);
|
|
|
|
|
|
if (d1 >= 0 && d1 < 15) {
|
|
|
|
|
|
m_dragStateA = DraggingPoint1;
|
|
|
|
|
|
setTracerHighlight(m_tracer1, true);
|
|
|
|
|
|
} else if (d2 >= 0 && d2 < 15) {
|
|
|
|
|
|
m_dragStateA = DraggingPoint2;
|
|
|
|
|
|
setTracerHighlight(m_tracer2, true);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
m_dragStateA = DraggingCurveA;
|
|
|
|
|
|
m_lastDragPixelA = pixel;
|
2026-01-04 16:54:55 +08:00
|
|
|
|
}
|
2026-04-23 09:10:28 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-04 16:54:55 +08:00
|
|
|
|
|
2026-04-23 09:10:28 +08:00
|
|
|
|
// ===== 模式B:拖拽端点或整体(非编辑模式) =====
|
|
|
|
|
|
if (m_type == TypeB_Polyline && !shiftPressed && !m_editingMode && !m_isAddingLine) {
|
|
|
|
|
|
QPointF pixel = me->localPos();
|
|
|
|
|
|
for (int i = 0; i < m_lines.size(); ++i) {
|
|
|
|
|
|
auto &item = m_lines[i];
|
|
|
|
|
|
if (item.startTracer->selectTest(pixel, false) >= 0 && item.startTracer->selectTest(pixel, false) < 10) {
|
|
|
|
|
|
if (s_activeItem && s_activeItem != this) s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = this;
|
|
|
|
|
|
setDragPointsVisible(true);
|
|
|
|
|
|
m_dragStateB = DraggingStartPoint;
|
|
|
|
|
|
m_draggedLineIndex = i;
|
|
|
|
|
|
m_bDragStart = pixel;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.endTracer->selectTest(pixel, false) >= 0 && item.endTracer->selectTest(pixel, false) < 10) {
|
|
|
|
|
|
if (s_activeItem && s_activeItem != this) s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = this;
|
|
|
|
|
|
setDragPointsVisible(true);
|
|
|
|
|
|
m_dragStateB = DraggingEndPoint;
|
|
|
|
|
|
m_draggedLineIndex = i;
|
|
|
|
|
|
m_bDragStart = pixel;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < m_lines.size(); ++i) {
|
|
|
|
|
|
double dist = m_lines[i].line->selectTest(pixel, false);
|
|
|
|
|
|
if (dist >= 0 && dist < 3) {
|
|
|
|
|
|
if (s_activeItem && s_activeItem != this) s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = this;
|
|
|
|
|
|
setDragPointsVisible(true);
|
|
|
|
|
|
m_dragStateB = DraggingLineOverall;
|
|
|
|
|
|
m_bDragStart = pixel;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 模式C:拖拽点或整体(已完成,非编辑模式) =====
|
|
|
|
|
|
if (m_type == TypeC_Closed && !shiftPressed && m_cFinished && !m_editingMode) {
|
|
|
|
|
|
QPointF pixel = me->localPos();
|
|
|
|
|
|
int hitPoint = -1;
|
|
|
|
|
|
for (int i = 0; i < m_labelsC.size(); ++i) {
|
|
|
|
|
|
if (m_labelsC[i]->selectTest(pixel, false) >= 0 && m_labelsC[i]->selectTest(pixel, false) < 10) {
|
|
|
|
|
|
hitPoint = i;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (hitPoint >= 0) {
|
|
|
|
|
|
if (s_activeItem && s_activeItem != this) s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = this;
|
|
|
|
|
|
setDragPointsVisible(true);
|
|
|
|
|
|
m_draggingPoint = true;
|
|
|
|
|
|
m_draggedPointIndex = hitPoint;
|
|
|
|
|
|
m_cDragStart = pixel;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
double curveDist = m_curveC ? m_curveC->selectTest(pixel, false) : -1;
|
|
|
|
|
|
if (curveDist >= 0 && curveDist < 3) {
|
|
|
|
|
|
if (s_activeItem && s_activeItem != this) s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = this;
|
|
|
|
|
|
setDragPointsVisible(true);
|
|
|
|
|
|
m_cDragging = true;
|
|
|
|
|
|
m_cDragStart = pixel;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (s_activeItem == this) {
|
|
|
|
|
|
s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = nullptr;
|
2026-01-04 16:54:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 鼠标移动
|
|
|
|
|
|
if (event->type() == QEvent::MouseMove) {
|
|
|
|
|
|
if (s_activeItem != this) return false;
|
|
|
|
|
|
|
|
|
|
|
|
if (m_type == TypeA_Sine) {
|
|
|
|
|
|
if (m_dragStateA == DraggingPoint1 || m_dragStateA == DraggingPoint2) {
|
|
|
|
|
|
double newY = m_plot->yAxis->pixelToCoord(me->localPos().y());
|
|
|
|
|
|
double currentY = (m_dragStateA == DraggingPoint1) ? m_orig_y1 : m_orig_y2;
|
|
|
|
|
|
double deltaY = newY - (currentY + m_offsetYA);
|
|
|
|
|
|
double newOrigY = currentY + deltaY;
|
|
|
|
|
|
newOrigY = qBound(m_depth - 100, newOrigY, m_depth + 100);
|
|
|
|
|
|
if (m_dragStateA == DraggingPoint1) m_orig_y1 = newOrigY;
|
|
|
|
|
|
else m_orig_y2 = newOrigY;
|
|
|
|
|
|
updateCurveFromTargets();
|
|
|
|
|
|
updateCurvePosition();
|
|
|
|
|
|
updateTracers();
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} else if (m_dragStateA == DraggingCurveA) {
|
|
|
|
|
|
QPointF current = me->localPos();
|
|
|
|
|
|
double oldX = m_plot->xAxis->pixelToCoord(m_lastDragPixelA.x());
|
|
|
|
|
|
double newX = m_plot->xAxis->pixelToCoord(current.x());
|
|
|
|
|
|
double oldY = m_plot->yAxis->pixelToCoord(m_lastDragPixelA.y());
|
|
|
|
|
|
double newY = m_plot->yAxis->pixelToCoord(current.y());
|
|
|
|
|
|
double dx = newX - oldX;
|
|
|
|
|
|
double dy = newY - oldY;
|
|
|
|
|
|
m_offsetXA += dx;
|
|
|
|
|
|
m_offsetYA += dy;
|
|
|
|
|
|
updateCurvePosition();
|
|
|
|
|
|
updateTracers();
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
m_lastDragPixelA = current;
|
2026-04-23 16:42:00 +08:00
|
|
|
|
updateLabelPosition();
|
2026-04-23 09:10:28 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (m_type == TypeB_Polyline && m_dragStateB != IdleB) {
|
|
|
|
|
|
QPointF current = me->localPos();
|
|
|
|
|
|
double oldX = m_plot->xAxis->pixelToCoord(m_bDragStart.x());
|
|
|
|
|
|
double newX = m_plot->xAxis->pixelToCoord(current.x());
|
|
|
|
|
|
double oldY = m_plot->yAxis->pixelToCoord(m_bDragStart.y());
|
|
|
|
|
|
double newY = m_plot->yAxis->pixelToCoord(current.y());
|
|
|
|
|
|
double dx = newX - oldX;
|
|
|
|
|
|
double dy = newY - oldY;
|
|
|
|
|
|
if (m_dragStateB == DraggingLineOverall) {
|
|
|
|
|
|
m_offsetXB += dx;
|
|
|
|
|
|
m_offsetYB += dy;
|
|
|
|
|
|
updateLinesPosition();
|
2026-04-23 16:42:00 +08:00
|
|
|
|
updateLabelPosition();
|
2026-04-23 09:10:28 +08:00
|
|
|
|
} else if (m_dragStateB == DraggingStartPoint || m_dragStateB == DraggingEndPoint) {
|
|
|
|
|
|
int idx = m_draggedLineIndex;
|
|
|
|
|
|
if (idx >= 0 && idx < m_lines.size()) {
|
|
|
|
|
|
LineItem &item = m_lines[idx];
|
|
|
|
|
|
if (m_dragStateB == DraggingStartPoint) {
|
|
|
|
|
|
item.startOrig.rx() += dx;
|
|
|
|
|
|
item.startOrig.ry() += dy;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
item.endOrig.rx() += dx;
|
|
|
|
|
|
item.endOrig.ry() += dy;
|
|
|
|
|
|
}
|
|
|
|
|
|
item.line->start->setCoords(item.startOrig.x() + m_offsetXB, item.startOrig.y() + m_offsetYB);
|
|
|
|
|
|
item.line->end->setCoords(item.endOrig.x() + m_offsetXB, item.endOrig.y() + m_offsetYB);
|
|
|
|
|
|
updateLineEndpoints(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
m_bDragStart = current;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
if (m_cDragging) {
|
|
|
|
|
|
QPointF current = me->localPos();
|
|
|
|
|
|
double oldX = m_plot->xAxis->pixelToCoord(m_cDragStart.x());
|
|
|
|
|
|
double newX = m_plot->xAxis->pixelToCoord(current.x());
|
|
|
|
|
|
double oldY = m_plot->yAxis->pixelToCoord(m_cDragStart.y());
|
|
|
|
|
|
double newY = m_plot->yAxis->pixelToCoord(current.y());
|
|
|
|
|
|
double dx = newX - oldX;
|
|
|
|
|
|
double dy = newY - oldY;
|
|
|
|
|
|
m_offsetXC += dx;
|
|
|
|
|
|
m_offsetYC += dy;
|
|
|
|
|
|
for (int i = 0; i < m_pointsC.size(); ++i) {
|
|
|
|
|
|
m_labelsC[i]->position->setCoords(m_pointsC[i].x() + m_offsetXC, m_pointsC[i].y() + m_offsetYC);
|
|
|
|
|
|
}
|
|
|
|
|
|
updatePolylineC(true);
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
m_cDragStart = current;
|
2026-04-23 16:42:00 +08:00
|
|
|
|
updateLabelPosition();
|
2026-04-23 09:10:28 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
} else if (m_draggingPoint) {
|
|
|
|
|
|
QPointF current = me->localPos();
|
|
|
|
|
|
double oldX = m_plot->xAxis->pixelToCoord(m_cDragStart.x());
|
|
|
|
|
|
double newX = m_plot->xAxis->pixelToCoord(current.x());
|
|
|
|
|
|
double oldY = m_plot->yAxis->pixelToCoord(m_cDragStart.y());
|
|
|
|
|
|
double newY = m_plot->yAxis->pixelToCoord(current.y());
|
|
|
|
|
|
double dx = newX - oldX;
|
|
|
|
|
|
double dy = newY - oldY;
|
|
|
|
|
|
m_pointsC[m_draggedPointIndex].rx() += dx;
|
|
|
|
|
|
m_pointsC[m_draggedPointIndex].ry() += dy;
|
|
|
|
|
|
m_labelsC[m_draggedPointIndex]->position->setCoords(m_pointsC[m_draggedPointIndex].x() + m_offsetXC,
|
|
|
|
|
|
m_pointsC[m_draggedPointIndex].y() + m_offsetYC);
|
|
|
|
|
|
updatePolylineC(true);
|
|
|
|
|
|
m_plot->replot();
|
|
|
|
|
|
m_cDragStart = current;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 鼠标释放:发射 dataChanged 信号(仅非编辑模式)
|
|
|
|
|
|
if (event->type() == QEvent::MouseButtonRelease && me->button() == Qt::LeftButton) {
|
|
|
|
|
|
if (s_activeItem == this && !m_editingMode) {
|
|
|
|
|
|
if (m_type == TypeA_Sine && m_dragStateA != IdleA) {
|
|
|
|
|
|
setTracerHighlight(m_tracer1, false);
|
|
|
|
|
|
setTracerHighlight(m_tracer2, false);
|
|
|
|
|
|
m_dragStateA = IdleA;
|
|
|
|
|
|
emit dataChanged();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} else if (m_type == TypeB_Polyline && m_dragStateB != IdleB) {
|
|
|
|
|
|
m_dragStateB = IdleB;
|
|
|
|
|
|
m_draggedLineIndex = -1;
|
|
|
|
|
|
emit dataChanged();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} else if (m_type == TypeC_Closed) {
|
|
|
|
|
|
if (m_cDragging) {
|
|
|
|
|
|
m_cDragging = false;
|
|
|
|
|
|
emit dataChanged();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} else if (m_draggingPoint) {
|
|
|
|
|
|
m_draggingPoint = false;
|
|
|
|
|
|
m_draggedPointIndex = -1;
|
|
|
|
|
|
emit dataChanged();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-23 09:38:17 +08:00
|
|
|
|
|
|
|
|
|
|
if (s_activeItem == this) {
|
|
|
|
|
|
s_activeItem->deactivate();
|
|
|
|
|
|
s_activeItem = nullptr;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2026-04-23 09:10:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 新建裂缝 ====================
|
2026-04-23 16:42:00 +08:00
|
|
|
|
bool CPickFrac::createNewCrack(double depth, QString type)
|
2026-04-23 09:10:28 +08:00
|
|
|
|
{
|
2026-04-23 16:42:00 +08:00
|
|
|
|
int iType = 1;
|
|
|
|
|
|
QColor m_lineColor;
|
|
|
|
|
|
QString m_typeName;
|
|
|
|
|
|
if("高导缝" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 1;
|
|
|
|
|
|
m_lineColor.setNamedColor("#FF0000");
|
|
|
|
|
|
m_typeName = "高导缝";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("高阻缝" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 1;
|
|
|
|
|
|
m_lineColor.setNamedColor("#400040");
|
|
|
|
|
|
m_typeName = "高阻缝";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("诱导缝" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 1;
|
|
|
|
|
|
m_lineColor.setNamedColor("#00FFFF");
|
|
|
|
|
|
m_typeName = "诱导缝";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("层理" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 1;
|
|
|
|
|
|
m_lineColor.setNamedColor("#00FF00");
|
|
|
|
|
|
m_typeName = "层理";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("侵蚀面" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 1;
|
|
|
|
|
|
m_lineColor.setNamedColor("#409600");
|
|
|
|
|
|
m_typeName = "侵蚀面";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("断层" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 1;
|
|
|
|
|
|
m_lineColor.setNamedColor("#A65300");
|
|
|
|
|
|
m_typeName = "断层";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("自定义1" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 1;
|
|
|
|
|
|
m_lineColor.setNamedColor("#000000");
|
|
|
|
|
|
m_typeName = "自定义1";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("自定义2" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 1;
|
|
|
|
|
|
m_lineColor.setNamedColor("#000000");
|
|
|
|
|
|
m_typeName = "自定义2";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("网状缝" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 2;
|
|
|
|
|
|
m_lineColor.setNamedColor("#808000");
|
|
|
|
|
|
m_typeName = "网状缝";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("垂直缝" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 2;
|
|
|
|
|
|
m_lineColor.setNamedColor("#FF0000");
|
|
|
|
|
|
m_typeName = "垂直缝";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("孔洞" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 3;
|
|
|
|
|
|
m_lineColor.setNamedColor("#FF8064");
|
|
|
|
|
|
m_typeName = "孔洞";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("气孔" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 3;
|
|
|
|
|
|
m_lineColor.setNamedColor("#FFFF00");
|
|
|
|
|
|
m_typeName = "气孔";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("砾石" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 3;
|
|
|
|
|
|
m_lineColor.setNamedColor("#000096");
|
|
|
|
|
|
m_typeName = "砾石";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("结核" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 3;
|
|
|
|
|
|
m_lineColor.setNamedColor("#A65300");
|
|
|
|
|
|
m_typeName = "结核";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if("团块" == type)
|
|
|
|
|
|
{
|
|
|
|
|
|
iType = 3;
|
|
|
|
|
|
m_lineColor.setNamedColor("#000000");
|
|
|
|
|
|
m_typeName = "团块";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// int iType,
|
|
|
|
|
|
// QString type
|
2026-04-23 09:10:28 +08:00
|
|
|
|
// 从配置文件中查找第一个匹配 iType 的定义,获取颜色和线宽
|
|
|
|
|
|
FRAC_DEF_Crack def;
|
|
|
|
|
|
bool found = false;
|
|
|
|
|
|
for (const FRAC_DEF_Crack &d : m_FracDef) {
|
|
|
|
|
|
if (d.iType == iType) {
|
|
|
|
|
|
def = d;
|
|
|
|
|
|
found = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!found) {
|
|
|
|
|
|
def.iType = iType;
|
2026-04-23 16:42:00 +08:00
|
|
|
|
def.crColor = m_lineColor;
|
2026-04-23 09:10:28 +08:00
|
|
|
|
def.nLineWidth = 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!m_myCustomPlot) return false;
|
|
|
|
|
|
double xMin = m_myCustomPlot->xAxis->range().lower;
|
|
|
|
|
|
double xMax = m_myCustomPlot->xAxis->range().upper;
|
|
|
|
|
|
double xCenter = (xMin + xMax) / 2.0;
|
|
|
|
|
|
double xWidth = xMax - xMin;
|
|
|
|
|
|
double yPos = -depth;
|
|
|
|
|
|
|
|
|
|
|
|
DraggableCrackItem *item = nullptr;
|
|
|
|
|
|
|
2026-04-23 16:42:00 +08:00
|
|
|
|
def.crColor = m_lineColor;
|
|
|
|
|
|
def.csName = m_typeName;
|
2026-04-23 09:10:28 +08:00
|
|
|
|
if (iType == 1) {
|
|
|
|
|
|
item = new DraggableCrackItem(m_myCustomPlot, DraggableCrackItem::TypeA_Sine, def.crColor, def.nLineWidth);
|
2026-04-23 16:42:00 +08:00
|
|
|
|
item->csName = m_typeName;
|
|
|
|
|
|
item->setLabelInfo(m_typeName, 0);
|
2026-04-23 09:10:28 +08:00
|
|
|
|
double amplitude = 0.5;
|
|
|
|
|
|
double phase = 0.0;
|
2026-04-23 16:42:00 +08:00
|
|
|
|
double width = xWidth;
|
2026-04-23 09:10:28 +08:00
|
|
|
|
double xScale = 360.0 / width;
|
|
|
|
|
|
double centerY = -(depth + amplitude);
|
|
|
|
|
|
item->setSineData(centerY, amplitude, phase, xScale, width);
|
|
|
|
|
|
item->setCrackCode(def.iCode);
|
|
|
|
|
|
connect(item, &DraggableCrackItem::dataChanged, this, &CPickFrac::saveToFile);
|
|
|
|
|
|
connect(item, &DraggableCrackItem::removeMe, this, &CPickFrac::onRemoveCrackItem);
|
|
|
|
|
|
m_items.append(item);
|
|
|
|
|
|
bool saved = saveToFile();
|
|
|
|
|
|
m_myCustomPlot->replot();
|
|
|
|
|
|
return saved;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (iType == 2) {
|
|
|
|
|
|
item = new DraggableCrackItem(m_myCustomPlot, DraggableCrackItem::TypeB_Polyline, def.crColor, def.nLineWidth);
|
2026-04-23 16:42:00 +08:00
|
|
|
|
item->csName = m_typeName;
|
|
|
|
|
|
item->setLabelInfo(m_typeName, 0);
|
2026-04-23 09:10:28 +08:00
|
|
|
|
item->setCrackCode(def.iCode);
|
|
|
|
|
|
connect(item, &DraggableCrackItem::dataChanged, this, &CPickFrac::saveToFile);
|
|
|
|
|
|
connect(item, &DraggableCrackItem::removeMe, this, &CPickFrac::onRemoveCrackItem);
|
|
|
|
|
|
m_items.append(item);
|
|
|
|
|
|
item->startEditing();
|
|
|
|
|
|
m_myCustomPlot->replot();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (iType == 3) {
|
|
|
|
|
|
item = new DraggableCrackItem(m_myCustomPlot, DraggableCrackItem::TypeC_Closed, def.crColor, def.nLineWidth);
|
2026-04-23 16:42:00 +08:00
|
|
|
|
item->csName = m_typeName;
|
|
|
|
|
|
item->setLabelInfo(m_typeName, 0);
|
2026-04-23 09:10:28 +08:00
|
|
|
|
item->setCrackCode(def.iCode);
|
|
|
|
|
|
connect(item, &DraggableCrackItem::dataChanged, this, &CPickFrac::saveToFile);
|
|
|
|
|
|
connect(item, &DraggableCrackItem::removeMe, this, &CPickFrac::onRemoveCrackItem);
|
|
|
|
|
|
m_items.append(item);
|
|
|
|
|
|
item->startEditing();
|
|
|
|
|
|
m_myCustomPlot->replot();
|
|
|
|
|
|
return true;
|
2026-01-04 16:54:55 +08:00
|
|
|
|
}
|
2026-04-23 09:10:28 +08:00
|
|
|
|
return false;
|
2026-01-04 16:54:55 +08:00
|
|
|
|
}
|
2026-04-23 16:42:00 +08:00
|
|
|
|
|
|
|
|
|
|
void CPickFrac::setShowHide(QString names, int nameShow, int angleShow, int digitCapacity)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (DraggableCrackItem* item : m_items)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(names.contains(item->csName))
|
|
|
|
|
|
{
|
|
|
|
|
|
item->setShow(true);
|
|
|
|
|
|
item->m_labelText->setVisible(false);
|
|
|
|
|
|
if(angleShow == 0 && nameShow == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
item->setLabelInfo(item->csName, -1, -1, digitCapacity);
|
|
|
|
|
|
item->m_labelText->setVisible(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(angleShow == 1 && nameShow == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
item->setLabelInfo("", item->DIPorS, item->DIR, digitCapacity);
|
|
|
|
|
|
item->m_labelText->setVisible(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(angleShow == 1 && nameShow == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
item->setLabelInfo(item->csName, item->DIPorS, item->DIR, digitCapacity);
|
|
|
|
|
|
item->m_labelText->setVisible(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
item->setShow(false);
|
|
|
|
|
|
item->m_labelText->setVisible(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
m_myCustomPlot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|