Bond.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. #include "Bond.h"
  2. #include <QDebug>
  3. #include <QPair>
  4. #include <QSet>
  5. #include <QMap>
  6. #include <cmath>
  7. Bond::Bond(QWidget* parent)
  8. : QWidget(parent)
  9. {
  10. }
  11. void Bond::UpdataGenerateTestData()
  12. {
  13. //// 生成测试数据:2x2 PCB,每个PCB 2x2 PT矩阵,每个PT矩阵 2x3固晶点
  14. //int pcbIndex = 0;
  15. //int dieIndex = 0;
  16. //std::srand(std::time(nullptr));
  17. //for (int pcbRow = 0; pcbRow < 2; ++pcbRow) {
  18. // for (int pcbCol = 0; pcbCol < 2; ++pcbCol) {
  19. // int iPcbMatId = ++pcbIndex;
  20. // pcbDimensions[iPcbMatId] = qMakePair(2, 2); // PCB包含2x2 PT矩阵
  21. // int ptIndex = 0;
  22. // for (int ptRow = 0; ptRow < 2; ++ptRow) {
  23. // for (int ptCol = 0; ptCol < 2; ++ptCol) {
  24. // int iPtMatId = ++ptIndex;
  25. // ptDimensions[iPcbMatId][iPtMatId] = qMakePair(2, 3); // PT矩阵包含2x3固晶点
  26. // for (int dieRow = 0; dieRow < 2; ++dieRow) {
  27. // for (int dieCol = 0; dieCol < 3; ++dieCol) {
  28. // ns_mat::POINT_INFO_STRUCT point;
  29. // point.stIndex.iPcbMatId = iPcbMatId;
  30. // point.stIndex.iPtMatId = iPtMatId;
  31. // point.stIndex.iPcbRow = pcbRow;
  32. // point.stIndex.iPcbCol = pcbCol;
  33. // point.stIndex.iPtRow = dieRow;
  34. // point.stIndex.iPtCol = dieCol;
  35. // point.stIndex.iIndex = ++dieIndex;
  36. // point.stBondStatus.bDieStatus = static_cast<ns_mat::DIE_STATUS>(std::rand() % 7);
  37. // bondData.append(point);
  38. // }
  39. // }
  40. // }
  41. // }
  42. // }
  43. //}
  44. }
  45. /*
  46. void Bond::initFrom(QWidget* parent) {
  47. m_pScene = new QGraphicsScene(parent);
  48. m_pView = new BondGraphicsView(m_pScene);
  49. int width = parent->width();
  50. int height = parent->height();
  51. // Step 1: 收集PCB全局布局信息
  52. QMap<QPair<int, int>, int> pcbPosMap;
  53. QSet<int> uniquePcbIds;
  54. foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
  55. QPair<int, int> pos(point.stIndex.iPcbRow, point.stIndex.iPcbCol);
  56. if (!pcbPosMap.contains(pos)) {
  57. pcbPosMap[pos] = point.stIndex.iPcbMatId;
  58. }
  59. uniquePcbIds.insert(point.stIndex.iPcbMatId);
  60. }
  61. // 计算PCB全局行列数
  62. int maxPcbRow = 0, maxPcbCol = 0;
  63. for (const QPair<int, int>& pos : pcbPosMap.keys()) {
  64. maxPcbRow = qMax(maxPcbRow, pos.first);
  65. maxPcbCol = qMax(maxPcbCol, pos.second);
  66. }
  67. int pcbRows = maxPcbRow + 1;
  68. int pcbCols = maxPcbCol + 1;
  69. // Step 2: 计算PCB布局参数
  70. qreal margin = width / maxPcbCol * 0.05;
  71. qreal pcbSpacing = margin;
  72. int fontSize = qMax(static_cast<int>(margin), 1);
  73. QFont font;
  74. font.setPointSize(fontSize);
  75. qreal totalWidth = width - 2 * margin;
  76. qreal totalHeight = height - 2 * margin;
  77. qreal pcbWidth = (totalWidth - (pcbCols - 1) * pcbSpacing) / pcbCols;
  78. qreal pcbHeight = (totalHeight - (pcbRows - 1) * pcbSpacing) / pcbRows;
  79. // Step 3: 预处理数据分组
  80. QMap<int, QMap<int, QList<ns_mat::POINT_INFO_STRUCT>>> groupedData;
  81. foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
  82. groupedData[point.stIndex.iPcbMatId][point.stIndex.iPtMatId].append(point);
  83. }
  84. // 绘制PCB并记录位置
  85. QMap<int, QRectF> pcbRects;
  86. for (int row = 0; row < pcbRows; ++row) {
  87. for (int col = 0; col < pcbCols; ++col) {
  88. QPair<int, int> pos(row, col);
  89. if (pcbPosMap.contains(pos)) {
  90. int pcbId = pcbPosMap[pos];
  91. QRectF rect(
  92. margin + col * (pcbWidth + pcbSpacing),
  93. margin + row * (pcbHeight + pcbSpacing),
  94. pcbWidth,
  95. pcbHeight
  96. );
  97. pcbRects[pcbId] = rect;
  98. // 绘制PCB背景
  99. QGraphicsRectItem* pcbItem = new QGraphicsRectItem(rect);
  100. pcbItem->setBrush(QColor("#e1d4e6"));
  101. m_pScene->addItem(pcbItem);
  102. // 添加PCB标签
  103. QGraphicsTextItem* text = new QGraphicsTextItem(QString(tr("PCB%1")).arg(pcbId));
  104. text->setFont(font);
  105. qreal fixedHeight = qMin(pcbWidth / std::ceil(static_cast<qreal>(groupedData[pcbId].keys().size()) / std::ceil(std::sqrt(groupedData[pcbId].keys().size()))) * 0.1
  106. , pcbHeight / std::ceil(std::sqrt(groupedData[pcbId].keys().size())) * 0.1);
  107. qreal actualHeight = text->boundingRect().height();
  108. if (actualHeight > 0) {
  109. qreal scaleFactor = fixedHeight / actualHeight;
  110. text->setScale(scaleFactor);
  111. }
  112. text->setPos(rect.x(), rect.y());
  113. m_pScene->addItem(text);
  114. }
  115. }
  116. }
  117. // Step 4: 绘制PT矩阵和固晶点
  118. foreach(int pcbId, uniquePcbIds) {
  119. QRectF pcbRect = pcbRects.value(pcbId);
  120. if (!pcbRect.isValid()) continue;
  121. // 获取当前PCB的所有PT矩阵
  122. QList<int> ptMatIds = groupedData[pcbId].keys();
  123. int ptMatCount = ptMatIds.size();
  124. if (ptMatCount == 0) continue;
  125. // 计算PT矩阵布局行列数(方形布局)
  126. int ptRows = std::ceil(std::sqrt(ptMatCount));
  127. int ptCols = std::ceil(static_cast<qreal>(ptMatCount) / ptRows);
  128. while (ptRows * ptCols < ptMatCount) ptCols++;
  129. qreal ptMargin = qMin(pcbWidth / ptCols * 0.1, pcbHeight / ptRows * 0.1);
  130. int fontSize_1 = qMax(static_cast<int>(ptMargin), 1);
  131. QFont font_1;
  132. font_1.setPointSize(fontSize_1);
  133. // 计算PT矩阵尺寸
  134. qreal ptWidth = (pcbRect.width() - (ptCols + 1) * ptMargin) / ptCols;
  135. qreal ptHeight = (pcbRect.height() - (ptRows + 1) * ptMargin) / ptRows;
  136. // 绘制每个PT矩阵
  137. for (int i = 0; i < ptMatIds.size(); ++i) {
  138. int ptId = ptMatIds[i];
  139. int row = i / ptCols;
  140. int col = i % ptCols;
  141. QRectF ptRect(
  142. pcbRect.x() + col * (ptWidth + ptMargin) + ptMargin,
  143. pcbRect.y() + row * (ptHeight + ptMargin) + ptMargin,
  144. ptWidth,
  145. ptHeight
  146. );
  147. // 绘制PT矩阵背景
  148. QGraphicsRectItem* ptItem = new QGraphicsRectItem(ptRect);
  149. ptItem->setBrush(QColor("#d5e4f8"));
  150. m_pScene->addItem(ptItem);
  151. // 添加PT矩阵标签
  152. QGraphicsTextItem* ptText = new QGraphicsTextItem(QString(tr("PT矩阵%1")).arg(ptId));
  153. ptText->setFont(font_1);
  154. qreal fixedHeight_1 = qMin(ptWidth / ptDimensions[pcbId][ptId].second * 0.3, ptHeight / ptDimensions[pcbId][ptId].first * 0.3);
  155. qreal actualHeight_1 = ptText->boundingRect().height();
  156. if (actualHeight_1 > 0) {
  157. qreal scaleFactor_1 = fixedHeight_1 / actualHeight_1;
  158. ptText->setScale(scaleFactor_1);
  159. }
  160. ptText->setPos(ptRect.x(), ptRect.y());
  161. m_pScene->addItem(ptText);
  162. // Step 5: 绘制固晶点
  163. QList<ns_mat::POINT_INFO_STRUCT> points = groupedData[pcbId][ptId];
  164. if (points.isEmpty()) continue;
  165. // 获取固晶点矩阵尺寸
  166. QPair<int, int> dieDims = ptDimensions[pcbId][ptId];
  167. int dieRows = dieDims.first;
  168. int dieCols = dieDims.second;
  169. qreal dieMargin = qMin(ptWidth / dieCols * 0.3, ptHeight / dieRows * 0.3);
  170. // 计算固晶点尺寸
  171. qreal dieWidth = (ptRect.width() - (dieCols + 1) * dieMargin) / dieCols;
  172. qreal dieHeight = (ptRect.height() - (dieRows + 1) * dieMargin) / dieRows;
  173. int fontSize_2 = qMax(static_cast<int>(qMin(dieWidth, dieHeight) * 0.2), 1);
  174. QFont font_2;
  175. font_2.setPointSize(fontSize_2);
  176. foreach(const ns_mat::POINT_INFO_STRUCT & point, points) {
  177. // 计算固晶点位置
  178. QRectF dieRect(
  179. ptRect.x() + point.stIndex.iPtCol * (dieWidth + dieMargin) + dieMargin,
  180. ptRect.y() + point.stIndex.iPtRow * (dieHeight + dieMargin) + dieMargin,
  181. dieWidth,
  182. dieHeight
  183. );
  184. // 绘制固晶点
  185. BondItem* dieItem = new BondItem(point);
  186. dieItem->setRect(dieRect);
  187. m_pScene->addItem(dieItem);
  188. // 添加固晶点编号
  189. QGraphicsTextItem* dieText = new QGraphicsTextItem(dieItem);
  190. dieText->setPlainText("PT" + QString::number(point.stIndex.iIndex));
  191. dieText->setFont(font_2);
  192. dieText->setPos(dieRect.center() - QPointF(dieText->boundingRect().width() / 2,
  193. dieText->boundingRect().height() / 2));
  194. }
  195. }
  196. }
  197. m_pView->setScene(m_pScene);
  198. m_pView->resize(width, height);
  199. }
  200. */
  201. void Bond::initFrom(QWidget* parent)
  202. {
  203. if (bondData.size() == 0 && m_pCViewInterface == nullptr)
  204. {
  205. return;
  206. }
  207. m_pScene = new QGraphicsScene(parent);
  208. m_pView = new BondGraphicsView(m_pScene);
  209. m_pView->setCViewInterface(m_pCViewInterface);
  210. int width = parent->width();
  211. int height = parent->height();
  212. double maxWidth = maxPoint.x() - minPoint.x();
  213. double maxHeight = maxPoint.y() - minPoint.y();
  214. double ratio = 0.0;
  215. if (maxHeight > maxWidth)
  216. {
  217. ratio = maxHeight / (width - 100);
  218. }
  219. else
  220. {
  221. ratio = maxWidth / (width - 100);
  222. }
  223. //目前没提供pt固晶点大小,以下用测试大小,后续可替换(实际大小,接口替换处)
  224. int dieWidth = 3000;
  225. int dieHeight = 3000;
  226. //m_pCViewInterface->GetViewMatrix()->GetBondDieSize(bondData[0].stIndex.iPcbMatId, dieWidth, dieHeight);
  227. QFont matrixFont;
  228. double matrixFontSize = qMin(dieWidth / ratio, dieHeight / ratio) * 0.1;
  229. matrixFont.setPointSizeF(matrixFontSize); // 使用浮点大小
  230. for (int i = 0; i < bondData.size(); ++i)
  231. {
  232. // 绘制固晶点
  233. //转换大小
  234. double dieWidthr = dieWidth / ratio;
  235. double dieHeightr = dieHeight / ratio;
  236. double diex, diey;
  237. diex = (bondData[i].stBondStatus.stAlnBondPosition.x - minPoint.x() + dieWidth) / ratio;
  238. diey = (bondData[i].stBondStatus.stAlnBondPosition.y - minPoint.y() + dieHeight) / ratio;
  239. // 计算固晶点位置
  240. QRectF dieRect(
  241. diex,
  242. diey,
  243. dieWidthr,
  244. dieHeightr
  245. );
  246. BondItem* dieItem = new BondItem(bondData[i]);
  247. dieItem->setRect(dieRect);
  248. dieItem->setZValue(1.0);
  249. m_pScene->addItem(dieItem);
  250. // 添加固晶点编号
  251. QGraphicsTextItem* dieText = new QGraphicsTextItem(dieItem);
  252. dieText->setPlainText("PT" + QString::number(bondData[i].stIndex.iIndex));
  253. double dieFontSize = qMin(dieWidthr, dieHeightr) * 0.2;
  254. QFont font;
  255. font.setPointSizeF(dieFontSize); // 使用浮点大小
  256. dieText->setFont(font);
  257. dieText->setPos(dieRect.center() - QPointF(dieText->boundingRect().width() / 2,
  258. dieText->boundingRect().height() / 2));
  259. }
  260. QPen ptpen(Qt::blue, 0.5);
  261. QPen pcbpen(Qt::red, 0.5);
  262. QPen subpen(Qt::black, 0.5);
  263. //绘制pt矩阵和Pcb矩阵
  264. POINT_INFO_STRUCT maxPcbPoint = m_vptMaxPoints[0];
  265. POINT_INFO_STRUCT minPcbPoint = m_vptMinPoints[0];
  266. int pcbmatx, pcbmaty, pcbmatWidth, pcbmatHeight;
  267. QVector<POINT_INFO_STRUCT> maxSubPoints;
  268. QVector<POINT_INFO_STRUCT> minSubPoints;
  269. for (int i = 0;i < m_vptMaxPoints.size();i++) {
  270. if (minPcbPoint.stIndex.iPcbRow != m_vptMinPoints[i].stIndex.iPcbRow || minPcbPoint.stIndex.iPcbCol != m_vptMinPoints[i].stIndex.iPcbCol) {
  271. //绘制pcb矩阵
  272. pcbmatx = (minPcbPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.4 * dieWidth) / ratio;
  273. pcbmaty = (minPcbPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.4 * dieHeight) / ratio;
  274. pcbmatWidth = (maxPcbPoint.stBondStatus.stAlnBondPosition.x - minPcbPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.2) / ratio;
  275. pcbmatHeight = (maxPcbPoint.stBondStatus.stAlnBondPosition.y - minPcbPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.2) / ratio;
  276. QRectF pcbRect(
  277. pcbmatx,
  278. pcbmaty,
  279. pcbmatWidth,
  280. pcbmatHeight
  281. );
  282. // 绘制PCB矩阵背景
  283. QGraphicsRectItem* pcbItem = new QGraphicsRectItem(pcbRect);
  284. pcbItem->setPen(pcbpen);
  285. //ptItem->setBrush(QColor("#d5e4f8"));
  286. m_pScene->addItem(pcbItem);
  287. // 添加PCB标签
  288. QRectF pcbTextRect(
  289. pcbmatx,
  290. pcbmaty,
  291. dieWidth / ratio * 0.6,
  292. dieHeight / ratio * 0.2
  293. );
  294. QGraphicsRectItem* pcbTextItem = new QGraphicsRectItem(pcbTextRect);
  295. pcbTextItem->setPen(Qt::NoPen);
  296. m_pScene->addItem(pcbTextItem);
  297. QGraphicsTextItem* pcbText = new QGraphicsTextItem(pcbTextItem);
  298. pcbText->setPlainText(QString(QString(tr("Pcb%1*%2")).arg(minPcbPoint.stIndex.iPcbRow).arg(minPcbPoint.stIndex.iPcbCol)));
  299. pcbText->setFont(matrixFont);
  300. // 将文本居中于 pcbTextRect
  301. pcbText->setPos(pcbTextRect.center() - QPointF(pcbText->boundingRect().width() / 2,
  302. pcbText->boundingRect().height() / 2));
  303. pcbText->setFont(matrixFont);
  304. maxSubPoints.append(maxPcbPoint);
  305. minSubPoints.append(minPcbPoint);
  306. maxPcbPoint = m_vptMaxPoints[i];
  307. minPcbPoint = m_vptMinPoints[i];
  308. }
  309. else {
  310. if (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.x > maxPcbPoint.stBondStatus.stAlnBondPosition.x)
  311. maxPcbPoint = m_vptMaxPoints[i];
  312. if (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x < minPcbPoint.stBondStatus.stAlnBondPosition.x)
  313. minPcbPoint = m_vptMinPoints[i];
  314. if (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.y > maxPcbPoint.stBondStatus.stAlnBondPosition.y)
  315. maxPcbPoint = m_vptMaxPoints[i];
  316. if (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y < minPcbPoint.stBondStatus.stAlnBondPosition.y)
  317. minPcbPoint = m_vptMinPoints[i];
  318. }
  319. int ptmatx, ptmaty, ptmatWidth, ptmatHeight;
  320. ptmatx = (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.7 * dieWidth) / ratio ;
  321. ptmaty = (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.7 * dieHeight) / ratio ;
  322. ptmatWidth = (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.x - m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x +dieWidth*1.6)/ratio;
  323. ptmatHeight = (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.y - m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y + dieHeight*1.6) / ratio;
  324. QRectF ptRect(
  325. ptmatx,
  326. ptmaty,
  327. ptmatWidth,
  328. ptmatHeight
  329. );
  330. //qDebug() << m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x << " " << m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y;
  331. //qDebug() << m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.x << " " << m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.y;
  332. // 绘制PT矩阵背景
  333. QGraphicsRectItem* ptItem = new QGraphicsRectItem(ptRect);
  334. ptItem->setPen(ptpen);
  335. //ptItem->setBrush(QColor("#d5e4f8"));
  336. m_pScene->addItem(ptItem);
  337. // 添加PT矩阵标签
  338. QRectF ptTextRect(
  339. ptmatx,
  340. ptmaty,
  341. dieWidth/ratio* 0.6,
  342. dieHeight / ratio * 0.2
  343. );
  344. QGraphicsRectItem* ptTextItem = new QGraphicsRectItem(ptTextRect);
  345. ptTextItem->setPen(Qt::NoPen);
  346. m_pScene->addItem(ptTextItem);
  347. QGraphicsTextItem* ptText = new QGraphicsTextItem(ptTextItem);
  348. ptText->setPlainText(QString(tr("PtMat%1")).arg(m_vptMinPoints[i].stIndex.iPtMatId));
  349. ptText->setFont(matrixFont);
  350. // 将文本居中于 ptTextRect
  351. ptText->setPos(ptTextRect.center()- QPointF(ptText->boundingRect().width() / 2,
  352. ptText->boundingRect().height() / 2));
  353. }
  354. pcbmatx = (minPcbPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.4 * dieWidth) / ratio;
  355. pcbmaty = (minPcbPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.4 * dieHeight) / ratio;
  356. pcbmatWidth = (maxPcbPoint.stBondStatus.stAlnBondPosition.x - minPcbPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.2) / ratio;
  357. pcbmatHeight = (maxPcbPoint.stBondStatus.stAlnBondPosition.y - minPcbPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.2) / ratio;
  358. QRectF pcbRect(
  359. pcbmatx,
  360. pcbmaty,
  361. pcbmatWidth,
  362. pcbmatHeight
  363. );
  364. // 绘制PCB矩阵背景
  365. QGraphicsRectItem* pcbItem = new QGraphicsRectItem(pcbRect);
  366. pcbItem->setPen(pcbpen);
  367. //ptItem->setBrush(QColor("#d5e4f8"));
  368. m_pScene->addItem(pcbItem);
  369. // 添加PCB标签
  370. QRectF pcbTextRect(
  371. pcbmatx,
  372. pcbmaty,
  373. dieWidth / ratio * 0.6,
  374. dieHeight / ratio * 0.2
  375. );
  376. QGraphicsRectItem* pcbTextItem = new QGraphicsRectItem(pcbTextRect);
  377. pcbTextItem->setPen(Qt::NoPen);
  378. m_pScene->addItem(pcbTextItem);
  379. QGraphicsTextItem* pcbText = new QGraphicsTextItem(pcbTextItem);
  380. pcbText->setPlainText(QString(QString(tr("Pcb%1*%2")).arg(minPcbPoint.stIndex.iPcbRow).arg(minPcbPoint.stIndex.iPcbCol)));
  381. pcbText->setFont(matrixFont);
  382. // 将文本居中于 pcbTextRect
  383. pcbText->setPos(pcbTextRect.center() - QPointF(pcbText->boundingRect().width() / 2,
  384. pcbText->boundingRect().height() / 2));
  385. pcbText->setFont(matrixFont);
  386. //绘制sub矩阵
  387. maxSubPoints.append(maxPcbPoint);
  388. minSubPoints.append(minPcbPoint);
  389. POINT_INFO_STRUCT maxSubPoint = maxSubPoints[0];
  390. POINT_INFO_STRUCT minSubPoint = minSubPoints[0];
  391. int submatx, submaty, submatWidth, submatHeight;
  392. for (int i = 0;i < maxSubPoints.size();i++) {
  393. if (maxSubPoint.stIndex.iPcbMatId != maxSubPoints[i].stIndex.iPcbMatId) {
  394. submatx = (minSubPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.1 * dieWidth) / ratio;
  395. submaty = (minSubPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.1 * dieHeight) / ratio;
  396. submatWidth = (maxSubPoint.stBondStatus.stAlnBondPosition.x - minSubPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.8) / ratio;
  397. submatHeight = (maxSubPoint.stBondStatus.stAlnBondPosition.y - minSubPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.8) / ratio;
  398. QRectF subRect(
  399. submatx,
  400. submaty,
  401. submatWidth,
  402. submatHeight
  403. );
  404. // 绘制SUB矩阵背景
  405. QGraphicsRectItem* subItem = new QGraphicsRectItem(subRect);
  406. subItem->setPen(subpen);
  407. //ptItem->setBrush(QColor("#d5e4f8"));
  408. m_pScene->addItem(subItem);
  409. // 添加PCB标签
  410. QRectF subTextRect(
  411. submatx,
  412. submaty,
  413. dieWidth / ratio * 0.6,
  414. dieHeight / ratio * 0.2
  415. );
  416. QGraphicsRectItem* subTextItem = new QGraphicsRectItem(subTextRect);
  417. subTextItem->setPen(Qt::NoPen);
  418. m_pScene->addItem(subTextItem);
  419. QGraphicsTextItem* subText = new QGraphicsTextItem(subTextItem);
  420. subText->setPlainText(QString(QString(tr("Sub%1")).arg(minSubPoint.stIndex.iPcbMatId)));
  421. subText->setFont(matrixFont);
  422. // 将文本居中于 pcbTextRect
  423. subText->setPos(subTextRect.center() - QPointF(subText->boundingRect().width() / 2,
  424. subText->boundingRect().height() / 2));
  425. subText->setFont(matrixFont);
  426. }
  427. else {
  428. if (maxSubPoints[i].stBondStatus.stAlnBondPosition.x > maxSubPoint.stBondStatus.stAlnBondPosition.x)
  429. maxSubPoint = maxSubPoints[i];
  430. if (minSubPoints[i].stBondStatus.stAlnBondPosition.x < minSubPoint.stBondStatus.stAlnBondPosition.x)
  431. minSubPoint = minSubPoints[i];
  432. if (maxSubPoints[i].stBondStatus.stAlnBondPosition.y > maxSubPoint.stBondStatus.stAlnBondPosition.y)
  433. maxSubPoint = maxSubPoints[i];
  434. if (minSubPoints[i].stBondStatus.stAlnBondPosition.y < minSubPoint.stBondStatus.stAlnBondPosition.y)
  435. minSubPoint = minSubPoints[i];
  436. }
  437. }
  438. submatx = (minSubPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.1 * dieWidth) / ratio;
  439. submaty = (minSubPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.1 * dieHeight) / ratio;
  440. submatWidth = (maxSubPoint.stBondStatus.stAlnBondPosition.x - minSubPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.8) / ratio;
  441. submatHeight = (maxSubPoint.stBondStatus.stAlnBondPosition.y - minSubPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.8) / ratio;
  442. QRectF subRect(
  443. submatx,
  444. submaty,
  445. submatWidth,
  446. submatHeight
  447. );
  448. QGraphicsRectItem* subItem = new QGraphicsRectItem(subRect);
  449. // 设置边框颜色为红色,线宽为2
  450. subItem->setPen(subpen);
  451. // 绘制SUB矩阵背景
  452. //ptItem->setBrush(QColor("#d5e4f8"));
  453. m_pScene->addItem(subItem);
  454. // 添加PCB标签
  455. QRectF subTextRect(
  456. submatx,
  457. submaty,
  458. dieWidth / ratio * 0.6,
  459. dieHeight / ratio * 0.2
  460. );
  461. QGraphicsRectItem* subTextItem = new QGraphicsRectItem(subTextRect);
  462. subTextItem->setPen(Qt::NoPen);
  463. m_pScene->addItem(subTextItem);
  464. QGraphicsTextItem* subText = new QGraphicsTextItem(subTextItem);
  465. subText->setPlainText(QString(QString(tr("Sub%1")).arg(minSubPoint.stIndex.iPcbMatId)));
  466. subText->setFont(matrixFont);
  467. // 将文本居中于 pcbTextRect
  468. subText->setPos(subTextRect.center() - QPointF(subText->boundingRect().width() / 2,
  469. subText->boundingRect().height() / 2));
  470. subText->setFont(matrixFont);
  471. m_pView->setScene(m_pScene);
  472. m_pView->resize(width, height);
  473. // 创建一个 QPixmap 对象用于保存绘制的图像
  474. globalPixmap = QPixmap(width, height);
  475. globalPixmap.fill(Qt::white); // 填充背景色为白色
  476. QPixmap originalPixmap = QPixmap::grabWidget(m_pView);
  477. // 设置目标尺寸(例如:宽度 200,高度 150)
  478. QSize targetSize(width, height);
  479. // 不保持比例,直接拉伸到指定尺寸
  480. QPixmap scaledPixmap = originalPixmap.scaled(
  481. targetSize,
  482. Qt::IgnoreAspectRatio,
  483. Qt::SmoothTransformation
  484. );
  485. globalPixmap = scaledPixmap;
  486. }
  487. void Bond::paintInitFrom(QWidget* parent) {
  488. /*
  489. int width = parent->width();
  490. int height = parent->height();
  491. globalPixmap = QPixmap(width, height);
  492. globalPixmap.fill(Qt::white);
  493. QPainter painter(&globalPixmap);
  494. painter.setRenderHint(QPainter::Antialiasing);
  495. QFont baseFont = painter.font();
  496. // Step 1: 收集PCB全局布局信息
  497. QMap<QPair<int, int>, int> pcbPosMap;
  498. QSet<int> uniquePcbIds;
  499. foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
  500. QPair<int, int> pos(point.stIndex.iPcbRow, point.stIndex.iPcbCol);
  501. if (!pcbPosMap.contains(pos)) {
  502. pcbPosMap[pos] = point.stIndex.iPcbMatId;
  503. }
  504. uniquePcbIds.insert(point.stIndex.iPcbMatId);
  505. }
  506. // 计算PCB全局行列数
  507. int maxPcbRow = 0, maxPcbCol = 0;
  508. for (const QPair<int, int>& pos : pcbPosMap.keys()) {
  509. maxPcbRow = qMax(maxPcbRow, pos.first);
  510. maxPcbCol = qMax(maxPcbCol, pos.second);
  511. }
  512. int pcbRows = maxPcbRow + 1;
  513. int pcbCols = maxPcbCol + 1;
  514. //TODO:yang
  515. maxPcbCol = 1;
  516. // Step 2: 计算PCB布局参数
  517. qreal margin = width / maxPcbCol * 0.05;
  518. qreal pcbSpacing = margin;
  519. qreal totalWidth = width - 2 * margin;
  520. qreal totalHeight = height - 2 * margin;
  521. qreal pcbWidth = (totalWidth - (pcbCols - 1) * pcbSpacing) / pcbCols;
  522. qreal pcbHeight = (totalHeight - (pcbRows - 1) * pcbSpacing) / pcbRows;
  523. // Step 3: 预处理数据分组
  524. QMap<int, QMap<int, QList<ns_mat::POINT_INFO_STRUCT>>> groupedData;
  525. foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
  526. groupedData[point.stIndex.iPcbMatId][point.stIndex.iPtMatId].append(point);
  527. }
  528. // 绘制PCB并记录位置
  529. QMap<int, QRectF> pcbRects;
  530. for (int row = 0; row < pcbRows; ++row) {
  531. for (int col = 0; col < pcbCols; ++col) {
  532. QPair<int, int> pos(row, col);
  533. if (pcbPosMap.contains(pos)) {
  534. int pcbId = pcbPosMap[pos];
  535. QRectF rect(
  536. margin + col * (pcbWidth + pcbSpacing),
  537. margin + row * (pcbHeight + pcbSpacing),
  538. pcbWidth,
  539. pcbHeight
  540. );
  541. pcbRects[pcbId] = rect;
  542. // 绘制PCB背景
  543. painter.setPen(Qt::NoPen);
  544. painter.setBrush(QColor("#e1d4e6"));
  545. painter.drawRect(rect);
  546. }
  547. }
  548. }
  549. // Step 4: 绘制PT矩阵和固晶点
  550. foreach(int pcbId, uniquePcbIds) {
  551. QRectF pcbRect = pcbRects.value(pcbId);
  552. if (!pcbRect.isValid()) continue;
  553. // 获取当前PCB的所有PT矩阵
  554. QList<int> ptMatIds = groupedData[pcbId].keys();
  555. int ptMatCount = ptMatIds.size();
  556. if (ptMatCount == 0) continue;
  557. // 计算PT矩阵布局行列数(方形布局)
  558. int ptRows = std::ceil(std::sqrt(ptMatCount));
  559. int ptCols = std::ceil(static_cast<qreal>(ptMatCount) / ptRows);
  560. while (ptRows * ptCols < ptMatCount) ptCols++;
  561. qreal ptMargin = qMin(pcbWidth / ptCols * 0.1, pcbHeight / ptRows * 0.1);
  562. // 计算PT矩阵尺寸
  563. qreal ptWidth = (pcbRect.width() - (ptCols + 1) * ptMargin) / ptCols;
  564. qreal ptHeight = (pcbRect.height() - (ptRows + 1) * ptMargin) / ptRows;
  565. // 绘制每个PT矩阵
  566. for (int i = 0; i < ptMatIds.size(); ++i) {
  567. int ptId = ptMatIds[i];
  568. int row = i / ptCols;
  569. int col = i % ptCols;
  570. QRectF ptRect(
  571. pcbRect.x() + col * (ptWidth + ptMargin) + ptMargin,
  572. pcbRect.y() + row * (ptHeight + ptMargin) + ptMargin,
  573. ptWidth,
  574. ptHeight
  575. );
  576. // 绘制PT矩阵背景
  577. painter.setPen(Qt::NoPen);
  578. painter.setBrush(QColor("#d5e4f8"));
  579. painter.drawRect(ptRect);
  580. // Step 5: 绘制固晶点
  581. QList<ns_mat::POINT_INFO_STRUCT> points = groupedData[pcbId][ptId];
  582. if (points.isEmpty()) continue;
  583. // 获取固晶点矩阵尺寸
  584. QPair<int, int> dieDims = ptDimensions[pcbId][ptId];
  585. int dieRows = dieDims.first;
  586. int dieCols = dieDims.second;
  587. qreal dieMargin = qMin(ptWidth / dieCols * 0.3, ptHeight / dieRows * 0.3);
  588. // 计算固晶点尺寸
  589. qreal dieWidth = (ptRect.width() - (dieCols + 1) * dieMargin) / dieCols;
  590. qreal dieHeight = (ptRect.height() - (dieRows + 1) * dieMargin) / dieRows;
  591. foreach(const ns_mat::POINT_INFO_STRUCT & point, points) {
  592. // 计算固晶点位置
  593. QRectF dieRect(
  594. ptRect.x() + point.stIndex.iPtCol * (dieWidth + dieMargin) + dieMargin,
  595. ptRect.y() + point.stIndex.iPtRow * (dieHeight + dieMargin) + dieMargin,
  596. dieWidth,
  597. dieHeight
  598. );
  599. // 绘制固晶点
  600. painter.setPen(Qt::NoPen);
  601. //painter.setBrush(getColorByStatus(point.stBondStatus.bDieStatus));
  602. painter.drawRect(dieRect);
  603. }
  604. }
  605. }
  606. painter.end();
  607. */
  608. }
  609. void Bond::UpdataVal(const std::vector<ns_mat::POINT_INFO_STRUCT>& stPointInfo)
  610. {
  611. bondData.clear();
  612. m_vptMaxPoints.clear();
  613. m_vptMinPoints.clear();
  614. if (stPointInfo.size() == 0)
  615. {
  616. return;
  617. }
  618. maxPoint = QPointF(stPointInfo[0].stBondStatus.stAlnBondPosition.x, stPointInfo[0].stBondStatus.stAlnBondPosition.y);
  619. minPoint = QPointF(stPointInfo[0].stBondStatus.stAlnBondPosition.x, stPointInfo[0].stBondStatus.stAlnBondPosition.y);
  620. QVector<POINT_INFO_STRUCT> ptMatrix;
  621. QMap<int, QMap<int, QVector<POINT_INFO_STRUCT>>> pcbMatrix;
  622. UINT iPcbMatId = stPointInfo[0].stIndex.iPcbMatId;
  623. UINT iPtId = stPointInfo[0].stIndex.iPtMatId;
  624. POINT_INFO_STRUCT ptMinPoint = stPointInfo[0];
  625. POINT_INFO_STRUCT ptMaxPoint = stPointInfo[0];
  626. QMap<int, QPointF> ptMinPointmap;
  627. QMap<int, QPointF> ptMaxPointmap;
  628. QMap<int, QMap<int, QPointF>> pcbMinPointmap;
  629. QMap<int, QMap<int, QPointF>> pcbMaxPointmap;
  630. int pcbRow = stPointInfo[0].stIndex.iPcbRow;
  631. int pcbCol = stPointInfo[0].stIndex.iPcbCol;
  632. int pcbId = 1;
  633. for (auto&a: stPointInfo)
  634. {
  635. bondData.append(a);
  636. if (a.stIndex.iPtMatId == iPtId)
  637. {
  638. ptMatrix.append(a);
  639. }
  640. else
  641. {
  642. m_vptMaxPoints.append(ptMaxPoint);
  643. m_vptMinPoints.append(ptMinPoint);
  644. iPtId = a.stIndex.iPtMatId;
  645. ptMaxPoint = a;
  646. ptMinPoint = a;
  647. }
  648. //遍历找到最小和最大边界点
  649. if (a.stBondStatus.stAlnBondPosition.x > maxPoint.x())
  650. {
  651. maxPoint.setX(a.stBondStatus.stAlnBondPosition.x);
  652. }
  653. if (a.stBondStatus.stAlnBondPosition.x < minPoint.x())
  654. {
  655. minPoint.setX(a.stBondStatus.stAlnBondPosition.x);
  656. }
  657. if (a.stBondStatus.stAlnBondPosition.y > maxPoint.y())
  658. {
  659. maxPoint.setY(a.stBondStatus.stAlnBondPosition.y);
  660. }
  661. if (a.stBondStatus.stAlnBondPosition.y < minPoint.y())
  662. {
  663. minPoint.setY(a.stBondStatus.stAlnBondPosition.y);
  664. }
  665. //判断pt最小和最大对角点
  666. if (a.stBondStatus.stAlnBondPosition.x > ptMaxPoint.stBondStatus.stAlnBondPosition.x)
  667. {
  668. ptMaxPoint = a;
  669. }
  670. if (a.stBondStatus.stAlnBondPosition.x < ptMinPoint.stBondStatus.stAlnBondPosition.x)
  671. {
  672. ptMinPoint = a;
  673. }
  674. if (a.stBondStatus.stAlnBondPosition.y > ptMaxPoint.stBondStatus.stAlnBondPosition.y)
  675. {
  676. ptMaxPoint = a;
  677. }
  678. if (a.stBondStatus.stAlnBondPosition.y < ptMinPoint.stBondStatus.stAlnBondPosition.y)
  679. {
  680. ptMinPoint = a;
  681. }
  682. // qDebug() << a.stBondStatus.stAlnBondPosition.x << " " << a.stBondStatus.stAlnBondPosition.y;
  683. }
  684. m_vptMaxPoints.append(ptMaxPoint);
  685. m_vptMinPoints.append(ptMinPoint);
  686. }
  687. QPixmap Bond::getGlobalPixmap() const
  688. {
  689. return globalPixmap;
  690. }
  691. void Bond::setBondInfo(ns_module::CViewInterface* CViewInterface)
  692. {
  693. m_pCViewInterface = CViewInterface;
  694. }