#include "ROICircularArc.h" ROICircularArc::ROICircularArc() { numHandles = 4; // midpoint handle + three handles on the arc activeHandleIdx = 0; circDir = ""; TwoPI = 2 * PI; roiType = ROIType::CircleArc; } void ROICircularArc::createROI(double midX, double midY) { midR = midY; midC = midX; radius = 100; sizeR = midR; sizeC = midC - radius; startPhi = PI * 0.25; extentPhi = PI * 1.5; circDir = "positive"; determineArcHandles(); updateArrowHandle(); updateStartRect2XLDHandle(handleWidth); } void ROICircularArc::drawROI(HTuple winID, double scaleFactor) { Q_UNUSED(scaleFactor); contour.GenCircleContourXld(HTuple(midR), HTuple(midC), HTuple(radius), HTuple(startPhi), HTuple((startPhi + extentPhi)), HTuple(circDir.toUtf8().data()), HTuple(1.0)); DispObj(contour, winID); int width = handleWidth; //DispRectangle2(winID, sizeR, sizeC, 0, width, width); //DispRectangle2(winID, midR, midC, 0, width, width); HObject ho_Rectangle; GenRectangle2ContourXld(&ho_Rectangle, sizeR, sizeC, 0, width, width); DispObj(ho_Rectangle, winID); GenRectangle2ContourXld(&ho_Rectangle, midR, midC, 0, width, width); DispObj(ho_Rectangle, winID); //if (startRect2XLD.IsInitialized()==false) { updateStartRect2XLDHandle(handleWidth); } DispObj(startRect2XLD, winID); //if (arrowHandleXLD.IsInitialized()==false) { updateArrowHandle(); } DispObj(arrowHandleXLD, winID); DispLine(winID, midR, midC, startR, startC); DispLine(winID, midR, midC, extentR, extentC); } double ROICircularArc::distToClosestHandle(double x, double y) { double max = 10000; double val[4]; val[0] = HMisc::DistancePp(y, x, midR, midC); // midpoint val[1] = HMisc::DistancePp(y, x, sizeR, sizeC); // border handle val[2] = HMisc::DistancePp(y, x, startR, startC); // border handle val[3] = HMisc::DistancePp(y, x, extentR, extentC); // border handle for (int i = 0; i < numHandles; i++) { if (val[i] < max) { max = val[i]; activeHandleIdx = i; } }// end of for return val[activeHandleIdx]; } void ROICircularArc::displayActive(HTuple winID, double scaleFactor) { Q_UNUSED(scaleFactor); HObject ho_Rectangle; double width = handleWidth; switch (activeHandleIdx) { case 0: //DispRectangle2(winID, midR, midC, 0, width, width); GenRectangle2ContourXld(&ho_Rectangle, midR, midC, 0, width, width); DispObj(ho_Rectangle, winID); break; case 1: //DispRectangle2(winID, sizeR, sizeC, 0, width, width); GenRectangle2ContourXld(&ho_Rectangle, sizeR, sizeC, 0, width, width); DispObj(ho_Rectangle, winID); break; case 2: //window.DispRectangle2(startR, startC, startPhi, 10, 2); DispObj(startRect2XLD, winID); break; case 3: DispObj(arrowHandleXLD, winID); break; } } void ROICircularArc::moveByHandle(double newX, double newY) { double distance; double dirX, dirY, prior, next, valMax, valMin; switch (activeHandleIdx) { case 0: // midpoint dirY = midR - newY; dirX = midC - newX; midR = newY; midC = newX; sizeR -= dirY; sizeC -= dirX; determineArcHandles(); break; case 1: // handle at circle border sizeR = newY; sizeC = newX; distance = HMisc::DistancePp(sizeR, sizeC, midR, midC); radius = distance; determineArcHandles(); break; case 2: // start handle for arc dirY = newY - midR; dirX = newX - midC; startPhi = atan2(-dirY, dirX); if (startPhi < 0) startPhi = PI + (startPhi + PI); setStartHandle(); prior = extentPhi; extentPhi = HMisc::AngleLl(midR, midC, startR, startC, midR, midC, extentR, extentC); if (extentPhi < 0 && prior > PI * 0.8) extentPhi = (PI + extentPhi) + PI; else if (extentPhi > 0 && prior < -PI * 0.7) extentPhi = -PI - (PI - extentPhi); break; case 3: // end handle for arc dirY = newY - midR; dirX = newX - midC; prior = extentPhi; next = atan2(-dirY, dirX); if (next < 0) next = PI + (next + PI); if (circDir == "positive" && startPhi >= next) extentPhi = (next + TwoPI) - startPhi; else if (circDir == "positive" && next > startPhi) extentPhi = next - startPhi; else if (circDir == "negative" && startPhi >= next) extentPhi = -1.0 * (startPhi - next); else if (circDir == "negative" && next > startPhi) extentPhi = -1.0 * (startPhi + TwoPI - next); valMax = std::max(std::abs(prior), std::abs(extentPhi)); valMin = std::max(std::abs(prior), std::abs(extentPhi)); if ((valMax - valMin) >= PI) { extentPhi = (circDir == "positive") ? -1.0 * valMin : valMin; } setExtentHandle(); break; } circDir = (extentPhi < 0) ? "negative" : "positive"; updateArrowHandle(); updateStartRect2XLDHandle(handleWidth); } QCursor ROICircularArc::showByHandle() { QCursor cursor; switch (activeHandleIdx) { case 0: // 鼠标在圆上的一点时 cursor = Qt::SizeAllCursor; break; case 1: // 鼠标在圆心上时 cursor = Qt::SizeBDiagCursor; break; } return cursor; } HRegion ROICircularArc::getRegion() { HRegion region; contour.GenCircleContourXld(HTuple(midR), HTuple(midC), HTuple(radius), HTuple(startPhi), HTuple((startPhi + extentPhi)), HTuple(circDir.toUtf8().data()), HTuple(1.0)); region = HRegion(contour); return region; } HTuple ROICircularArc::getROIData() { HTuple dat; dat.Clear(); dat[0] = midR; dat[1] = midC; dat[2] = radius; dat[3] = startPhi; dat[4] = extentPhi; return dat; } void ROICircularArc::setROIData(HTuple dat) { Q_UNUSED(dat); } void ROICircularArc::save(QDataStream &dataStream) { ROI::save(dataStream); int paranum;//参数数量 paranum = 14; dataStream << paranum;//先保存参数数量 dataStream << (int)1 << midR; dataStream << (int)2 << midC; dataStream << (int)3 << sizeR; dataStream << (int)4 << sizeC; dataStream << (int)5 << startR; dataStream << (int)6 << startC; dataStream << (int)7 << extentR; dataStream << (int)8 << extentC; dataStream << (int)9 << radius; dataStream << (int)10 << startPhi; dataStream << (int)11 << extentPhi; dataStream << (int)12 << TwoPI; dataStream << (int)13 << circDir; dataStream << (int)14 << m_strTitle; } void ROICircularArc::load(QDataStream &dataStream) { ROI::load(dataStream); int paranum;//参数数量 int para; dataStream >> paranum;//读取参数数量 for (int i = 0; i < paranum; i++) { dataStream >> para; switch (para) { case 1: dataStream >> midR; break; case 2: dataStream >> midC; break; case 3: dataStream >> sizeR; break; case 4: dataStream >> sizeC; break; case 5: dataStream >> startR; break; case 6: dataStream >> startC; break; case 7: dataStream >> extentR; break; case 8: dataStream >> extentC; break; case 9: dataStream >> radius; break; case 10: dataStream >> startPhi; break; case 11: dataStream >> extentPhi; break; case 12: dataStream >> TwoPI; break; case 13: dataStream >> circDir; break; case 14: dataStream >> m_strTitle; break; default: { qWarning() << "配置文档错误!"; } break; } } } void ROICircularArc::determineArcHandles() { setStartHandle(); setExtentHandle(); } void ROICircularArc::updateArrowHandle() { double row1, col1, row2, col2; double rowP1, colP1, rowP2, colP2; double length, dr, dc, halfHW, sign, angleRad; double headLength = handleWidth; double headWidth = handleWidth; row2 = extentR; col2 = extentC; angleRad = (startPhi + extentPhi) + PI * 0.5; sign = (circDir == "negative") ? -1.0 : 1.0; row1 = row2 + sign * sin(angleRad) * 20; col1 = col2 - sign * cos(angleRad) * 20; length = HMisc::DistancePp(row1, col1, row2, col2); if (length == 0) length = -1; dr = (row2 - row1) / length; dc = (col2 - col1) / length; halfHW = headWidth / 2.0; rowP1 = row1 + (length - headLength) * dr + halfHW * dc; rowP2 = row1 + (length - headLength) * dr - halfHW * dc; colP1 = col1 + (length - headLength) * dc - halfHW * dr; colP2 = col1 + (length - headLength) * dc + halfHW * dr; arrowHandleXLD.GenEmptyObj(); if (length == -1) arrowHandleXLD.GenContourPolygonXld(row1, col1); else { double rTmpDouble[5] = { 1, 2, 3 }; HTuple test(rTmpDouble, 5); HTuple rTmp; rTmp.Clear(); rTmp[0] = row1; rTmp[1] = row2; rTmp[2] = rowP1; rTmp[3] = row2; rTmp[4] = rowP2; rTmp[5] = row2; HTuple cTmp; cTmp.Clear(); cTmp[0] = col1; cTmp[1] = col2; cTmp[2] = colP1; cTmp[3] = col2; cTmp[4] = colP2; cTmp[5] = col2; arrowHandleXLD.GenContourPolygonXld(rTmp, cTmp); } } void ROICircularArc::updateStartRect2XLDHandle(int imageWidth) { startRect2XLD.GenEmptyObj(); startRect2XLD.GenRectangle2ContourXld(startR, startC, startPhi, imageWidth, imageWidth / 5.0); } void ROICircularArc::setStartHandle() { startR = midR - radius * sin(startPhi); startC = midC + radius * cos(startPhi); } void ROICircularArc::setExtentHandle() { extentR = midR - radius * sin(startPhi + extentPhi); extentC = midC + radius *cos(startPhi + extentPhi); } #ifndef QT_NO_DATASTREAM QDataStream &operator>>(QDataStream &in, ROICircularArc &data) { in >> data.midR >> data.midC >> data.sizeR >> data.sizeC >> data.startR >> data.startC >> data.extentR >> data.extentC >> data.radius >> data.startPhi >> data.extentPhi >> data.circDir >> data.TwoPI; return in; } QDataStream &operator<<(QDataStream &out, ROICircularArc &data) { out << data.midR << data.midC << data.sizeR << data.sizeC << data.startR << data.startC << data.extentR << data.extentC << data.radius << data.startPhi << data.extentPhi << data.circDir << data.TwoPI; return out; } #endif