#include "ToolDialog.h" #include #include #include #include #include #include ToolDialogImpl::ToolDialogImpl(QWidget* parent) : DllToolDialog(parent) { ui.setupUi(this); this->setWindowFlags(Qt::Dialog | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint /*| Qt::WindowStaysOnTopHint*/); connect(this, SIGNAL(sigUpdateUI()), this, SLOT(on_UpdateUI())); // 显示控件初始化 hwndUnit = new HWndUnit(this); Util::ShowUnitInWidget(ui.Image_widget, hwndUnit); hwndUnit->getHWndCtrl()->useROIController(&m_RoiController); connect(&m_RoiController, SIGNAL(ROIChange(const ViewMessage)), this, SLOT(on_ROIChange(const ViewMessage))); ROIRect2* roi = new ROIRect2(); roi->setTitle("R0"); m_RoiController.setROISign(ROIOperation::Negative); m_RoiController.setROIShape(roi); m_RoiController.mouseDownAction(50, 50); ROIRect2* roi1 = new ROIRect2(); roi1->setTitle("R1"); m_RoiController.setROISign(ROIOperation::Negative); m_RoiController.setROIShape(roi1); m_RoiController.mouseDownAction(150, 150); QString strPath = QCoreApplication::applicationDirPath() + "/Test.jpg"; try { m_Image.ReadImage(strPath.toStdString().c_str()); hwndUnit->ShowImage(m_Image); hwndUnit->Refresh(false); } catch (HException& exception) { // char m_szMsg[2048] = ""; // snprintf(m_szMsg, sizeof(m_szMsg), "Error #%u in %s: %s\n", exception.ErrorCode(), // exception.ProcName().TextA(), // exception.ErrorMessage().TextA()); // // qWarning() << m_szMsg; } m_fMeasureMin = 0; m_fMeasureMax = 0; m_fMeasureValue = 0; m_fJudgeMax = 100000; // 判断最大值 m_fJudgeMin = 1; // 判断最小值 m_fVlaueScale = 1; ui.dSpinBox_JudgeMax->setValue(m_fJudgeMax); ui.dSpinBox_JudgeMin->setValue(m_fJudgeMin); ui.dSpinBoxVlaueScale->setValue(m_fVlaueScale); { m_fSigma_0 = 1; //直线边缘点滤波系数 m_nThreshold_0 = 20; //直线边缘点阈值 m_nElementSize_0 = 10; //rake工具卡尺数 m_nMinPointsNum_0 = 4; //拟合直线最少点数 m_nTransitionMode_0 = 0; //直线边缘点极性 m_nSelectMode_0 = 0; //直线边缘点的位置 ui.dSpinBoxSigma0->setValue(m_fSigma_0); ui.spinBoxThreshold0->setValue(m_nThreshold_0); ui.spinBoxElementSize0->setValue(m_nElementSize_0); ui.spinBoxMinPointsNum0->setValue(m_nMinPointsNum_0); ui.comboBoxTransitionModd0->setCurrentIndex(m_nTransitionMode_0); ui.comboBoxSelectMode0->setCurrentIndex(m_nSelectMode_0); } { m_fSigma_1 = 1; //直线边缘点滤波系数 m_nThreshold_1 = 20; //直线边缘点阈值 m_nElementSize_1 = 10; //rake工具卡尺数 m_nMinPointsNum_1 = 4; //拟合直线最少点数 m_nTransitionMode_1 = 0; //直线边缘点极性 m_nSelectMode_1 = 0; //直线边缘点的位置 ui.dSpinBoxSigma1->setValue(m_fSigma_1); ui.spinBoxThreshold1->setValue(m_nThreshold_1); ui.spinBoxElementSize1->setValue(m_nElementSize_1); ui.spinBoxMinPointsNum1->setValue(m_nMinPointsNum_1); ui.comboBoxTransitionMode1->setCurrentIndex(m_nTransitionMode_1); ui.comboBoxSelectMode1->setCurrentIndex(m_nSelectMode_1); } } ToolDialogImpl::~ToolDialogImpl() { } VPEnum::RETURN_VALUE ToolDialogImpl::Execute() { m_fMeasureMin = 0; m_fMeasureMax = 0; m_nStatus = 0; try { hwndUnit->ShowImage(m_Image); hwndUnit->ShowObj(m_hoROI_R0, QColor(128, 222, 0)); hwndUnit->ShowObj(m_hoROI_R1, QColor(128, 222, 0)); hwndUnit->Refresh(); HObject ho_Regions0, ho_Regions1; m_fSigma_0 = ui.dSpinBoxSigma0->value(); m_nThreshold_0 = ui.spinBoxThreshold0->value(); m_nElementSize_0 = ui.spinBoxElementSize0->value(); m_nMinPointsNum_0 = ui.spinBoxMinPointsNum0->value(); m_nTransitionMode_0 = ui.comboBoxTransitionModd0->currentIndex(); m_fSigma_1 = ui.dSpinBoxSigma1->value(); m_nThreshold_1 = ui.spinBoxThreshold1->value(); m_nElementSize_1 = ui.spinBoxElementSize1->value(); m_nMinPointsNum_1 = ui.spinBoxMinPointsNum1->value(); m_nTransitionMode_1 = ui.comboBoxTransitionMode1->currentIndex(); HTuple hv_Point0_Row, hv_Point0_Column; Find_Edges(m_Image, &ho_Regions0, hv_roiDateR0[0], hv_roiDateR0[1], hv_roiDateR0[2], hv_roiDateR0[3], hv_roiDateR0[4], m_nElementSize_0, m_fSigma_0, m_nThreshold_0, m_nTransitionMode_0, m_nSelectMode_0, &hv_Point0_Row, &hv_Point0_Column); HTuple hv_Point1_Row, hv_Point1_Column; Find_Edges(m_Image, &ho_Regions1, hv_roiDateR1[0], hv_roiDateR1[1], hv_roiDateR1[2], hv_roiDateR1[3], hv_roiDateR1[4], m_nElementSize_1, m_fSigma_1, m_nThreshold_1, m_nTransitionMode_1, m_nSelectMode_1, &hv_Point1_Row, &hv_Point1_Column); HObject ho_Cross0, ho_Cross1; GenCrossContourXld(&ho_Cross0, hv_Point0_Row, hv_Point0_Column, 16, 0.785398); GenCrossContourXld(&ho_Cross1, hv_Point1_Row, hv_Point1_Column, 16, 0.785398); hwndUnit->ShowObj(ho_Cross0, QColor(255, 0, 0)); hwndUnit->ShowObj(ho_Cross1, QColor(0, 255, 0)); HObject ho_Line0; HTuple hv_Row1_0, hv_Column1_0, hv_Row2_0, hv_Column2_0; pts_to_best_line(&ho_Line0, hv_Point0_Row, hv_Point0_Column, m_nMinPointsNum_0, &hv_Row1_0, &hv_Column1_0, &hv_Row2_0, &hv_Column2_0, 0 ); HObject ho_Line1; HTuple hv_Row1_1, hv_Column1_1, hv_Row2_1, hv_Column2_1; pts_to_best_line(&ho_Line1, hv_Point1_Row, hv_Point1_Column, m_nMinPointsNum_1, &hv_Row1_1, &hv_Column1_1, &hv_Row2_1, &hv_Column2_1, 0 ); hwndUnit->ShowObj(ho_Line0, QColor(255, 0, 0)); hwndUnit->ShowObj(ho_Line1, QColor(255, 0, 0)); HTuple hvArea0, hvRow0, hvColumn0; AreaCenterPointsXld(ho_Line0, &hvArea0, &hvRow0, &hvColumn0); HTuple hvArea1, hvRow1, hvColumn1; AreaCenterPointsXld(ho_Line1, &hvArea1, &hvRow1, &hvColumn1); // 如果两条边,任意一条搜索失败,则提示错误 if ((hvArea0.TupleLength() == 0) || (hvArea1.TupleLength() == 0)) { m_fMeasureMin = 0; m_fMeasureMax = 0; hwndUnit->Refresh(true); m_nStatus = 2; return VPEnum::RETURN_VALUE::Error; } // 计算第一条变的投影点,用来显示垂线 HTuple hv_RowProj, hv_ColProj; ProjectionPl(hvRow1, hvColumn1, hv_Row1_0, hv_Column1_0, hv_Row2_0, hv_Column2_0, &hv_RowProj, &hv_ColProj); // 显示带箭头的垂线 HObject hoArrow; GenArrowContourXld(&hoArrow, hv_RowProj, hv_ColProj, hvRow1, hvColumn1, 50, 50); hwndUnit->ShowObj(hoArrow, QColor(0, 255, 0)); // 计算垂线的中心点,在该点上显示测量值文本 HTuple hvArea, hvRow, hvColumn; AreaCenterPointsXld(hoArrow, &hvArea, &hvRow, &hvColumn); // 将第一条线设置成无限延长线 HObject ho_ContourLin; { //直线方程y=k*x+b HTuple hv_Width, hv_Height; GetImageSize(m_Image, &hv_Width, &hv_Height); //特殊情况水平线 if (0 != (int((hv_Row2_0 - hv_Row1_0) == 0))) { GenContourPolygonXld(&ho_ContourLin, hv_Row2_0.TupleConcat(hv_Row2_0), HTuple(0).TupleConcat(hv_Width)); } else { HTuple hv_k, hv_b, hv_row1, hv_row2, hv_col1, hv_col2; hv_k = (hv_Column2_0 - hv_Column1_0) / (hv_Row2_0 - hv_Row1_0); hv_b = hv_Column2_0 - (hv_k * hv_Row2_0); hv_row1 = 0; hv_row2 = hv_Height - 1; hv_col1 = (hv_k * hv_row1) + hv_b; hv_col2 = (hv_k * hv_row2) + hv_b; GenContourPolygonXld(&ho_ContourLin, hv_row1.TupleConcat(hv_row2), hv_col1.TupleConcat(hv_col2)); } hwndUnit->ShowObj(ho_ContourLin, QColor(10, 0, 255)); } //计算线段的长度 HTuple hv_DistanceMin, hv_DistanceMax; DistanceSl( hv_Row1_0, hv_Column1_0, hv_Row2_0, hv_Column2_0, hv_Row1_1, hv_Column1_1, hv_Row2_1, hv_Column2_1, &hv_DistanceMin, &hv_DistanceMax); hwndUnit->ShowMsg(hv_DistanceMax, QColor(0, 255, 0), hvRow[0].D(), hvColumn[0].D()); m_fMeasureMin = hv_DistanceMin.D(); m_fMeasureMax = hv_DistanceMax.D(); // 显示基础线一定距离外的投影,用来观测测量结果是否为期望值 HObject ho_ParallelContours; GenParallelContourXld(ho_Line0, &ho_ParallelContours, "regression_normal", -hv_DistanceMin); hwndUnit->ShowObj(ho_ParallelContours, QColor(255, 0, 0)); // DebugDada GetDebugDataPtr()->Clear(); GetDebugDataPtr()->addLog("MaxValue", QString::number(m_fMeasureMax)); GetDebugDataPtr()->addLog("MinValue", QString::number(m_fMeasureMin)); GetDebugDataPtr()->addImage(m_Image); GetDebugDataPtr()->addObj(ho_ContourLin, qRgb(255, 0, 0));// 无限延长线 GetDebugDataPtr()->addObj(ho_Line1, qRgb(255, 0, 0));// 另外一条线段 GetDebugDataPtr()->addObj(hoArrow, qRgb(255, 0, 0));// 垂线 GetDebugDataPtr()->addMsg(hv_DistanceMax, QColor(0, 255, 0), hvRow[0].D(), hvColumn[0].D()); hwndUnit->Refresh(true); emit sigUpdateUI(); // 输出状态 if (m_fMeasureValue > m_fMeasureMax || m_fMeasureValue < m_fMeasureMax) { m_nStatus = 2; } else { m_nStatus = 1; } return VPEnum::RETURN_VALUE::Success; } catch (HException& exception) { char m_szMsg[2048] = ""; snprintf(m_szMsg, sizeof(m_szMsg), "Error #%u in %s: %s\n", exception.ErrorCode(), exception.ProcName().TextA(), exception.ErrorMessage().TextA()); qWarning() << "Execute() " << m_szMsg; hwndUnit->Refresh(true); m_nStatus = 2; } //emit sigUpdateUI(); //m_TestClass.SetValue(m_Value3); return VPEnum::RETURN_VALUE::Success; } void ToolDialogImpl::on_ROIChange(const ViewMessage& sign) { switch (sign) { case ViewMessage::MovingROI: { }break; case ViewMessage::UpdateROI: { ROI* roi = m_RoiController.getActiveROI(); if (roi == nullptr) { return; } if (roi->getTitle() == "R0") { hv_roiDateR0 = roi->getROIData(); try { GenRectangle2(&m_hoROI_R0, hv_roiDateR0[0], hv_roiDateR0[1], hv_roiDateR0[2], hv_roiDateR0[3], hv_roiDateR0[4]); } catch (...) {} } else { hv_roiDateR1 = roi->getROIData(); try { GenRectangle2(&m_hoROI_R1, hv_roiDateR1[0], hv_roiDateR1[1], hv_roiDateR1[2], hv_roiDateR1[3], hv_roiDateR1[4]); } catch (...) {} } Execute(); } break; case ViewMessage::CreatedROI: { ROI* roi = m_RoiController.getActiveROI(); if (roi == nullptr) { return; } if (roi->getTitle() == "R0") { hv_roiDateR0 = roi->getROIData(); try { GenRectangle2(&m_hoROI_R0, hv_roiDateR0[0], hv_roiDateR0[1], hv_roiDateR0[2], hv_roiDateR0[3], hv_roiDateR0[4]); } catch (...) {} } else { hv_roiDateR1 = roi->getROIData(); try { GenRectangle2(&m_hoROI_R1, hv_roiDateR1[0], hv_roiDateR1[1], hv_roiDateR1[2], hv_roiDateR1[3], hv_roiDateR1[4]); } catch (...) {} } } break; default: break; } } void ToolDialogImpl::Running(bool bRun) { } void ToolDialogImpl::timerEvent(QTimerEvent* event) { } bool ToolDialogImpl::Serialized(QDataStream& ar, bool bIsOut) { int paranum;//参数数量 if (bIsOut)//保存参数流程 { paranum = 21; ar << paranum;//先保存参数数量 ar << (int)1 << hv_roiDateR0; ar << (int)2 << hv_roiDateR1; ar << (int)3 << m_RoiController; ar << (int)4 << m_hoROI_R0; ar << (int)5 << m_hoROI_R1; ar << (int)6 << ui.dSpinBoxSigma0->value(); ar << (int)7 << ui.spinBoxThreshold0->value(); ar << (int)8 << ui.spinBoxElementSize0->value(); ar << (int)9 << ui.spinBoxMinPointsNum0->value(); ar << (int)10 << ui.comboBoxTransitionModd0->currentIndex(); ar << (int)11 << ui.comboBoxSelectMode0->currentIndex(); ar << (int)12 << ui.dSpinBoxSigma1->value(); ar << (int)13 << ui.spinBoxThreshold1->value(); ar << (int)14 << ui.spinBoxElementSize1->value(); ar << (int)15 << ui.spinBoxMinPointsNum1->value(); ar << (int)16 << ui.comboBoxTransitionMode1->currentIndex(); ar << (int)17 << ui.comboBoxSelectMode1->currentIndex(); ar << (int)18 << ui.comboBoxValueMode->currentIndex(); ar << (int)19 << ui.dSpinBoxVlaueScale->value(); ar << (int)20 << ui.dSpinBox_JudgeMax->value(); ar << (int)21 << ui.dSpinBox_JudgeMin->value(); } else//加载参数流程,参数加载顺序一定要跟保存顺序一致 { int para; ar >> paranum;//读取参数数量 for (int i = 0; i < paranum; i++) { ar >> para; switch (para) { case 1: ar >> hv_roiDateR0; break; case 2: ar >> hv_roiDateR1; break; case 3: ar >> m_RoiController; break; case 4: ar >> m_hoROI_R0; break; case 5: ar >> m_hoROI_R1; break; case 6: ar >> m_fSigma_0; break; case 7: ar >> m_nThreshold_0; break; case 8: ar >> m_nElementSize_0; break; case 9: ar >> m_nMinPointsNum_0; break; case 10: ar >> m_nTransitionMode_0; break; case 11: ar >> m_nSelectMode_0; break; case 12: ar >> m_fSigma_1; break; case 13: ar >> m_nThreshold_1; break; case 14: ar >> m_nElementSize_1; break; case 15: ar >> m_nMinPointsNum_1; break; case 16: ar >> m_nTransitionMode_1; break; case 17: ar >> m_nSelectMode_1; break; case 18: ar >> m_nValueMode; break; case 19: ar >> m_fVlaueScale; break; case 20: ar >> m_fJudgeMax; break; case 21: ar >> m_fJudgeMin; break; default: { qWarning() << "Serialized(In) Error"; return false; } break; } } ui.comboBoxValueMode->setCurrentIndex(m_nValueMode); ui.dSpinBoxVlaueScale->setValue(m_fVlaueScale); ui.dSpinBox_JudgeMax->setValue(m_fJudgeMax); ui.dSpinBox_JudgeMin->setValue(m_fJudgeMin); { ui.dSpinBoxSigma0->setValue(m_fSigma_0); ui.spinBoxThreshold0->setValue(m_nThreshold_0); ui.spinBoxElementSize0->setValue(m_nElementSize_0); ui.spinBoxMinPointsNum0->setValue(m_nMinPointsNum_0); ui.comboBoxTransitionModd0->setCurrentIndex(m_nTransitionMode_0); ui.comboBoxSelectMode0->setCurrentIndex(m_nSelectMode_0); } { ui.dSpinBoxSigma1->setValue(m_fSigma_1); ui.spinBoxThreshold1->setValue(m_nThreshold_1); ui.spinBoxElementSize1->setValue(m_nElementSize_1); ui.spinBoxMinPointsNum1->setValue(m_nMinPointsNum_1); ui.comboBoxTransitionMode1->setCurrentIndex(m_nTransitionMode_1); ui.comboBoxSelectMode1->setCurrentIndex(m_nSelectMode_1); } } return true; } void ToolDialogImpl::on_UpdateUI() { float fValue = 0.0; m_fVlaueScale = ui.dSpinBoxVlaueScale->value(); switch (ui.comboBoxValueMode->currentIndex() ) { case 0:fValue = (m_fMeasureMax + m_fMeasureMin) / 2.0; break; case 1:fValue = m_fMeasureMax; break; case 2:fValue = m_fMeasureMin; break; default: fValue = m_fMeasureMin; break; } ui.dSpinBoxMeasureValue->setValue(fValue); fValue = fValue * m_fVlaueScale; ui.doubleSpinBox_Vlalue->setValue(fValue); m_fMeasureValue = fValue; m_fMeasureMax = ui.dSpinBox_JudgeMax->value(); m_fMeasureMin = ui.dSpinBox_JudgeMin->value(); } /// /// 确定 /// void ToolDialogImpl::on_btnOK_clicked() { this->hide(); } /// /// 取消按钮 /// void ToolDialogImpl::on_btnCancel_clicked() { // 将本工具的恢复到打开工具之前的状态 RecoverData(); } /// /// 测试按钮 /// void ToolDialogImpl::on_btnExecute_clicked() { QElapsedTimer toolTimer; toolTimer.start(); // 发送事件 ToolEvent* pToolEvent = new ToolEvent(m_strPouName, m_strInstanceName, TOOL_EVENT_TYPE::TOOL_TRIGGER); QCoreApplication::sendEvent(m_pEventTarget, pToolEvent); // 统计返回值 VPEnum::RETURN_VALUE ret = pToolEvent->ret; double nExecTime = toolTimer.elapsed(); QString str; str = QString("耗时: %1 ms").arg(nExecTime, 0, 'G', 5); ui.label_time->setText(str); str = QString("状态: %1 ").arg(QMetaEnum::fromType().key((short)ret)); ui.label_state->setText(str); delete pToolEvent; } void ToolDialogImpl::Find_Edges(HObject ho_Image, HObject* ho_Regions, HTuple hv_Row, HTuple hv_Column, HTuple hv_Phi, HTuple hv_Length1, HTuple hv_Length2, HTuple hv_Elements, HTuple hv_Sigma, HTuple hv_Threshold, int nTransitionMode, int nSelectMode, HTuple* hv_ResultRow, HTuple* hv_ResultColumn) { // Local iconic variables HObject ho_RegionLines, ho_Rectangle, ho_Arrow1; // Local control variables HTuple hv_Cos, hv_Sin, hv_a, hv_b, hv_c, hv_d; HTuple hv_e, hv_f, hv_g, hv_h, hv_Row1, hv_Column1, hv_Row2; HTuple hv_Column2, hv_Width, hv_Height, hv_ATan, hv_DetectHeight; HTuple hv_DetectWidth, hv_Deg, hv_i, hv_RowC, hv_ColC; HTuple hv_Distance, hv_RowL2, hv_RowL1, hv_ColL2, hv_ColL1; HTuple hv_MsrHandle_Measure, hv_RowEdge, hv_ColEdge, hv_Amplitude; HTuple hv_tRow, hv_tCol, hv_t, hv_Number, hv_j; TupleCos(hv_Phi, &hv_Cos); TupleSin(hv_Phi, &hv_Sin); if (HDevWindowStack::IsOpen()) SetColor(HDevWindowStack::GetActive(), "red"); hv_a = ((-hv_Length1) * hv_Cos) - (hv_Length2 * hv_Sin); hv_b = ((-hv_Length1) * hv_Sin) + (hv_Length2 * hv_Cos); //gen_cross_contour_xld (Cross1, Row-b, Column+a, 6, Phi) hv_c = (hv_Length1 * hv_Cos) - (hv_Length2 * hv_Sin); hv_d = (hv_Length1 * hv_Sin) + (hv_Length2 * hv_Cos); //gen_cross_contour_xld (Cross2, Row-d, Column+c, 6, Phi) hv_e = (hv_Length1 * hv_Cos) + (hv_Length2 * hv_Sin); hv_f = (hv_Length1 * hv_Sin) - (hv_Length2 * hv_Cos); //gen_cross_contour_xld (Cross3, Row-f, Column+e, 6, Phi) hv_g = ((-hv_Length1) * hv_Cos) + (hv_Length2 * hv_Sin); hv_h = ((-hv_Length1) * hv_Sin) - (hv_Length2 * hv_Cos); //gen_cross_contour_xld (Cross4, Row-h, Column+g, 6, Phi) hv_Row1 = hv_Row + ((hv_f + hv_h) / 2); hv_Column1 = hv_Column + ((hv_a + hv_c) / 2); hv_Row2 = hv_Row + ((hv_b + hv_d) / 2); hv_Column2 = hv_Column + ((hv_e + hv_g) / 2); GenRegionLine(&ho_RegionLines, hv_Row1, hv_Column1, hv_Row2, hv_Column2); GetImageSize(ho_Image, &hv_Width, &hv_Height); GenEmptyObj(&(*ho_Regions)); (*hv_ResultRow) = HTuple(); (*hv_ResultColumn) = HTuple(); hv_ATan = hv_Phi; hv_DetectHeight = hv_Length1 * 2; hv_DetectWidth = hv_Length2 / 4; TupleDeg(hv_ATan, &hv_Deg); { HTuple end_val39 = hv_Elements; HTuple step_val39 = 1; for (hv_i = 1; hv_i.Continue(end_val39, step_val39); hv_i += step_val39) { hv_RowC = hv_Row1 + (((hv_Row2 - hv_Row1) * hv_i) / (hv_Elements + 1)); hv_ColC = hv_Column1 + (((hv_Column2 - hv_Column1) * hv_i) / (hv_Elements + 1)); if (0 != (HTuple(HTuple(HTuple(int(hv_RowC > (hv_Height - 1))).TupleOr(int(hv_RowC < 0))).TupleOr(int(hv_ColC > (hv_Width - 1)))).TupleOr(int(hv_ColC < 0)))) { continue; } if (0 != (int(hv_Elements == 1))) { DistancePp(hv_Row1, hv_Column1, hv_Row2, hv_Column2, &hv_Distance); GenRectangle2ContourXld(&ho_Rectangle, hv_RowC, hv_ColC, hv_Deg.TupleRad(), hv_DetectHeight / 2, hv_Distance / 2); } else { GenRectangle2ContourXld(&ho_Rectangle, hv_RowC, hv_ColC, hv_Deg.TupleRad(), hv_DetectHeight / 2, hv_DetectWidth / 2); } ConcatObj((*ho_Regions), ho_Rectangle, &(*ho_Regions)); if (0 != (int(hv_i == 1))) { //RowL2 := RowC+DetectHeight/2*sin(ATan) //RowL1 := RowC-DetectHeight/2*sin(ATan) //ColL2 := ColC-DetectHeight/2*cos(ATan) //ColL1 := ColC+DetectHeight/2*cos(ATan) hv_RowL2 = hv_RowC + ((hv_DetectHeight / 2) * ((-hv_ATan).TupleSin())); hv_RowL1 = hv_RowC - ((hv_DetectHeight / 2) * ((-hv_ATan).TupleSin())); hv_ColL2 = hv_ColC + ((hv_DetectHeight / 2) * ((-hv_ATan).TupleCos())); hv_ColL1 = hv_ColC - ((hv_DetectHeight / 2) * ((-hv_ATan).TupleCos())); gen_arrow_contour_xld(&ho_Arrow1, hv_RowL1, hv_ColL1, hv_RowL2, hv_ColL2, 25, 25); ConcatObj((*ho_Regions), ho_Arrow1, &(*ho_Regions)); } //Deg 是根据拟合线的角度加上90可得,拟合线的角度在-180到180之间(不包括-180),由开始点到到结束点的角度,例如:(0,0)到,(1,1)就是45度,(1,1)到,(0,0)就是-135度 GenMeasureRectangle2(hv_RowC, hv_ColC, hv_Deg.TupleRad(), hv_DetectHeight / 2, hv_DetectWidth / 2, hv_Width, hv_Height, "nearest_neighbor", &hv_MsrHandle_Measure); HTuple hv_Transition; switch (nTransitionMode) { case 0:hv_Transition = "all"; break; case 1:hv_Transition = "negative"; break; case 2:hv_Transition = "positive"; break; default:hv_Transition = "all"; break; } HTuple hv_Select; switch (nSelectMode) { case 0:hv_Select = "all"; break; case 1:hv_Select = "first"; break; case 2:hv_Select = "last"; break; default:hv_Select = "all"; break; } MeasurePos(ho_Image, hv_MsrHandle_Measure, hv_Sigma, hv_Threshold, hv_Transition, hv_Select, &hv_RowEdge, &hv_ColEdge, &hv_Amplitude, &hv_Distance); CloseMeasure(hv_MsrHandle_Measure); hv_tRow = 0; hv_tCol = 0; hv_t = 0; TupleLength(hv_RowEdge, &hv_Number); if (0 != (int(hv_Number < 1))) { continue; } { HTuple end_val101 = hv_Number - 1; HTuple step_val101 = 1; for (hv_j = 0; hv_j.Continue(end_val101, step_val101); hv_j += step_val101) { if (0 != (int((HTuple(hv_Amplitude[hv_j]).TupleAbs()) > hv_t))) { hv_tRow = HTuple(hv_RowEdge[hv_j]); hv_tCol = HTuple(hv_ColEdge[hv_j]); hv_t = HTuple(hv_Amplitude[hv_j]).TupleAbs(); } } } if (0 != (int(hv_t > 0))) { (*hv_ResultRow) = (*hv_ResultRow).TupleConcat(hv_tRow); (*hv_ResultColumn) = (*hv_ResultColumn).TupleConcat(hv_tCol); } } } TupleLength((*hv_ResultRow), &hv_Number); return; } void ToolDialogImpl::gen_arrow_contour_xld(HObject* ho_Arrow, HTuple hv_Row1, HTuple hv_Column1, HTuple hv_Row2, HTuple hv_Column2, HTuple hv_HeadLength, HTuple hv_HeadWidth) { // Local iconic variables HObject ho_TempArrow; // Local control variables HTuple hv_Length, hv_ZeroLengthIndices, hv_DR; HTuple hv_DC, hv_HalfHeadWidth, hv_RowP1, hv_ColP1, hv_RowP2; HTuple hv_ColP2, hv_Index; //This procedure generates arrow shaped XLD contours, //pointing from (Row1, Column1) to (Row2, Column2). //If starting and end point are identical, a contour consisting //of a single point is returned. // //input parameteres: //Row1, Column1: Coordinates of the arrows' starting points //Row2, Column2: Coordinates of the arrows' end points //HeadLength, HeadWidth: Size of the arrow heads in pixels // //output parameter: //Arrow: The resulting XLD contour // //The input tuples Row1, Column1, Row2, and Column2 have to be of //the same length. //HeadLength and HeadWidth either have to be of the same length as //Row1, Column1, Row2, and Column2 or have to be a single element. //If one of the above restrictions is violated, an error will occur. // // //Init GenEmptyObj(&(*ho_Arrow)); // //Calculate the arrow length DistancePp(hv_Row1, hv_Column1, hv_Row2, hv_Column2, &hv_Length); // //Mark arrows with identical start and end point //(set Length to -1 to avoid division-by-zero exception) hv_ZeroLengthIndices = hv_Length.TupleFind(0); if (0 != (hv_ZeroLengthIndices != -1)) { hv_Length[hv_ZeroLengthIndices] = -1; } // //Calculate auxiliary variables. hv_DR = (1.0 * (hv_Row2 - hv_Row1)) / hv_Length; hv_DC = (1.0 * (hv_Column2 - hv_Column1)) / hv_Length; hv_HalfHeadWidth = hv_HeadWidth / 2.0; // //Calculate end points of the arrow head. hv_RowP1 = (hv_Row1 + ((hv_Length - hv_HeadLength) * hv_DR)) + (hv_HalfHeadWidth * hv_DC); hv_ColP1 = (hv_Column1 + ((hv_Length - hv_HeadLength) * hv_DC)) - (hv_HalfHeadWidth * hv_DR); hv_RowP2 = (hv_Row1 + ((hv_Length - hv_HeadLength) * hv_DR)) - (hv_HalfHeadWidth * hv_DC); hv_ColP2 = (hv_Column1 + ((hv_Length - hv_HeadLength) * hv_DC)) + (hv_HalfHeadWidth * hv_DR); // //Finally create output XLD contour for each input point pair { HTuple end_val45 = (hv_Length.TupleLength()) - 1; HTuple step_val45 = 1; for (hv_Index = 0; hv_Index.Continue(end_val45, step_val45); hv_Index += step_val45) { if (0 != (HTuple(hv_Length[hv_Index]) == -1)) { //Create_ single points for arrows with identical start and end point GenContourPolygonXld(&ho_TempArrow, HTuple(hv_Row1[hv_Index]), HTuple(hv_Column1[hv_Index])); } else { //Create arrow contour GenContourPolygonXld(&ho_TempArrow, ((((HTuple(hv_Row1[hv_Index]).TupleConcat(HTuple(hv_Row2[hv_Index]))).TupleConcat(HTuple(hv_RowP1[hv_Index]))).TupleConcat(HTuple(hv_Row2[hv_Index]))).TupleConcat(HTuple(hv_RowP2[hv_Index]))).TupleConcat(HTuple(hv_Row2[hv_Index])), ((((HTuple(hv_Column1[hv_Index]).TupleConcat(HTuple(hv_Column2[hv_Index]))).TupleConcat(HTuple(hv_ColP1[hv_Index]))).TupleConcat(HTuple(hv_Column2[hv_Index]))).TupleConcat(HTuple(hv_ColP2[hv_Index]))).TupleConcat(HTuple(hv_Column2[hv_Index]))); } ConcatObj((*ho_Arrow), ho_TempArrow, &(*ho_Arrow)); } } } void ToolDialogImpl::GenArrowContourXld(HObject* ho_Arrow, HTuple hv_Row1, HTuple hv_Column1, HTuple hv_Row2, HTuple hv_Column2, HTuple hv_HeadLength, HTuple hv_HeadWidth) { // Local iconic variables HObject ho_TempArrow; // Local control variables HTuple hv_Length, hv_ZeroLengthIndices, hv_DR; HTuple hv_DC, hv_HalfHeadWidth, hv_RowP1, hv_ColP1, hv_RowP2; HTuple hv_ColP2, hv_RowP3, hv_ColP3, hv_RowP4, hv_ColP4; HTuple hv_Index; //Init GenEmptyObj(&(*ho_Arrow)); // //Calculate the arrow length DistancePp(hv_Row1, hv_Column1, hv_Row2, hv_Column2, &hv_Length); // //Mark arrows with identical start and end point //(set Length to -1 to avoid division-by-zero exception) hv_ZeroLengthIndices = hv_Length.TupleFind(0); if (0 != (int(hv_ZeroLengthIndices != -1))) { hv_Length[hv_ZeroLengthIndices] = -1; } // //Calculate auxiliary variables. hv_DR = (1.0 * (hv_Row2 - hv_Row1)) / hv_Length; hv_DC = (1.0 * (hv_Column2 - hv_Column1)) / hv_Length; hv_HalfHeadWidth = hv_HeadWidth / 2.0; // //Calculate end points of the arrow head. hv_RowP1 = (hv_Row1 + ((hv_Length - hv_HeadLength) * hv_DR)) + (hv_HalfHeadWidth * hv_DC); hv_ColP1 = (hv_Column1 + ((hv_Length - hv_HeadLength) * hv_DC)) - (hv_HalfHeadWidth * hv_DR); hv_RowP2 = (hv_Row1 + ((hv_Length - hv_HeadLength) * hv_DR)) - (hv_HalfHeadWidth * hv_DC); hv_ColP2 = (hv_Column1 + ((hv_Length - hv_HeadLength) * hv_DC)) + (hv_HalfHeadWidth * hv_DR); hv_RowP3 = (hv_Row1 + (hv_HeadLength * hv_DR)) + (hv_HalfHeadWidth * hv_DC); hv_ColP3 = (hv_Column1 + (hv_HeadLength * hv_DC)) - (hv_HalfHeadWidth * hv_DR); hv_RowP4 = (hv_Row1 + (hv_HeadLength * hv_DR)) - (hv_HalfHeadWidth * hv_DC); hv_ColP4 = (hv_Column1 + (hv_HeadLength * hv_DC)) + (hv_HalfHeadWidth * hv_DR); // //Finally create output XLD contour for each input point pair { HTuple end_val50 = (hv_Length.TupleLength()) - 1; HTuple step_val50 = 1; for (hv_Index = 0; hv_Index.Continue(end_val50, step_val50); hv_Index += step_val50) { if (0 != (int(HTuple(hv_Length[hv_Index]) == -1))) { //Create_ single points for arrows with identical start and end point GenContourPolygonXld(&ho_TempArrow, HTuple(hv_Row1[hv_Index]), HTuple(hv_Column1[hv_Index])); } else { //Create arrow contour GenContourPolygonXld(&ho_TempArrow, ((((((((HTuple(hv_Row1[hv_Index]).TupleConcat(HTuple(hv_RowP3[hv_Index]))).TupleConcat(HTuple(hv_Row1[hv_Index]))).TupleConcat(HTuple(hv_RowP4[hv_Index]))).TupleConcat(HTuple(hv_Row1[hv_Index]))).TupleConcat(HTuple(hv_Row2[hv_Index]))).TupleConcat(HTuple(hv_RowP1[hv_Index]))).TupleConcat(HTuple(hv_Row2[hv_Index]))).TupleConcat(HTuple(hv_RowP2[hv_Index]))).TupleConcat(HTuple(hv_Row2[hv_Index])), ((((((((HTuple(hv_Column1[hv_Index]).TupleConcat(HTuple(hv_ColP3[hv_Index]))).TupleConcat(HTuple(hv_Column1[hv_Index]))).TupleConcat(HTuple(hv_ColP4[hv_Index]))).TupleConcat(HTuple(hv_Column1[hv_Index]))).TupleConcat(HTuple(hv_Column2[hv_Index]))).TupleConcat(HTuple(hv_ColP1[hv_Index]))).TupleConcat(HTuple(hv_Column2[hv_Index]))).TupleConcat(HTuple(hv_ColP2[hv_Index]))).TupleConcat(HTuple(hv_Column2[hv_Index]))); } ConcatObj((*ho_Arrow), ho_TempArrow, &(*ho_Arrow)); } } return; } void ToolDialogImpl::pts_to_best_line(HObject* ho_Line, HTuple hv_Rows, HTuple hv_Cols, HTuple hv_ActiveNum, HTuple* hv_Row1, HTuple* hv_Col1, HTuple* hv_Row2, HTuple* hv_Col2, int nAlgorithmMode) { // Local iconic variables HObject ho_Contour; // Local control variables HTuple hv_Length, hv_Nr, hv_Nc, hv_Dist, hv_Length1; (*hv_Row1) = 0; (*hv_Col1) = 0; (*hv_Row2) = 0; (*hv_Col2) = 0; GenEmptyObj(&(*ho_Line)); TupleLength(hv_Cols, &hv_Length); if (0 != (HTuple(hv_Length >= hv_ActiveNum).TupleAnd(hv_ActiveNum > 1))) { GenContourPolygonXld(&ho_Contour, hv_Rows, hv_Cols); //"gauss" FitLineContourXld(ho_Contour, "tukey", hv_ActiveNum, 0, 5, 2, &(*hv_Row1), &(*hv_Col1), &(*hv_Row2), &(*hv_Col2), &hv_Nr, &hv_Nc, &hv_Dist); TupleLength(hv_Dist, &hv_Length1); if (0 != (hv_Length1 < 1)) { return; } GenContourPolygonXld(&(*ho_Line), (*hv_Row1).TupleConcat((*hv_Row2)), (*hv_Col1).TupleConcat((*hv_Col2))); } }