/* Constructor, in which all calibration parameters
         * and  auxiliary variables, flags and lists are initilized */
        public CalibrationAssistant()
        {
            //
            _imgQualityExaminer = new BackgroundWorker() { WorkerReportsProgress = true, WorkerSupportsCancellation = true };
            _imgQualityExaminer.DoWork += _imgQualityExaminer_DoWork;
            _imgQualityExaminer.ProgressChanged += _imgQualityExaminer_ProgressChanged;
            _imgQualityExaminer.RunWorkerCompleted += _imgQualityExaminer_RunWorkerCompleted;

            _addImagTasks = new List<string>();

            _imageTaskTimer = new System.Windows.Forms.Timer();
            _imageTaskTimer.Tick += _imageTaskTimer_Tick;

            CalibData = new ArrayList(15);
            mReferenceIndex = -1;
            mDescrFileName = "caltab_30mm.descr";
            mCalibValid = false;
            mCanCalib = true;
            mAtImgCoord = false;

            mReferenceImage = new HImage();
            mSimulatedImage = new HImage();

            mFilterSize = resetFilterSize;
            mMarkThresh = resetMarkThresh;
            mMinMarkDiam = resetMinMarkDiam;
            mInitThresh = resetInitThresh;
            mThreshDecr = resetThreshDecr;
            mMinThresh = resetMinThresh;
            mSmoothing = resetSmoothing;
            mMinContLength = resetMinContL;
            mMaxMarkDiam = resetMaxMarkDiam;

            mWarnLevel = 70;
            mImageTests = QUALITY_ISSUE_TEST_ALL;
            mSequenceTests = QUALITY_ISSUE_TEST_ALL;
            mSeqQualityList = new ArrayList(15);
            procedure = new QualityProcedures();

            mThickness = 630;       // micrometer
            mCameraType = CAMERA_TYP_AREA_SCAN_DIV;
            mCellWidth = 8300.0;    // nm
            mCellHeight = 8300.0;    // nm
            mFocalLength = 8000;      // micrometer
            isTelecentric = false;
            mKappa = 0.0;
            mK1 = 0.0;
            mK2 = 0.0;
            mK3 = 0.0;
            mP1 = 0.0;
            mP2 = 0.0;
            mMotionVx = 0.0;
            mMotionVy = 500.0;
            mMotionVz = 0.0;

            NotifyCalibObserver = new CalibDelegate(dummy);
        }
        /// <summary>
        /// Determine s(or updates) the basic information for this
        /// calibration image, which are the values for the region
        /// plate, the center marks, and the estimated pose.
        /// The flag <c>mPlateStatus</c> describes the evaluation
        /// of the computation process.
        /// If desired the quality assessment can be recalculated
        /// as well.
        /// </summary>
        /// <param name="updateQuality">
        /// Triggers the recalculation of the quality assessment for
        /// this calibration image
        /// </param>
        public void UpdateCaltab(bool updateQuality)
        {
            HTuple worldX, worldY;
            HTuple unit = new HTuple("m");

            bool failed            = false;
            QualityProcedures proc = new QualityProcedures();
            string            descrFile;
            HTuple            startCamp;

            ErrorMessage = "";


            _mCaltabRegion.Dispose();
            _mMarkCenter.Dispose();
            _mEstimatedWCS.Dispose();

            //reset this variable
            _mMarkCenterRows = new HTuple();

            PlateStatus = CalibrationAssistant.PS_NOT_FOUND;

            descrFile = _mAssistant.getDesrcFile();

            try
            {
                _mCaltabRegion = _mImage.FindCaltab(descrFile,
                                                    (int)_mAssistant.mFilterSize,
                                                    (int)_mAssistant.mMarkThresh,
                                                    (int)_mAssistant.mMinMarkDiam);

                PlateStatus = CalibrationAssistant.PS_MARKS_FAILED;

                //-- Quality issue measurements --
                if (updateQuality)
                {
                    _mQualityIssuesList.Clear();
                    failed = _mAssistant.testQualityIssues(this);
                }

                startCamp        = _mAssistant.getCameraParams(this);
                _mMarkCenterRows = _mImage.FindMarksAndPose(_mCaltabRegion,
                                                            descrFile,
                                                            startCamp,
                                                            (int)_mAssistant.mInitThresh,
                                                            (int)_mAssistant.mThreshDecr,
                                                            (int)_mAssistant.mMinThresh,
                                                            _mAssistant.mSmoothing,
                                                            _mAssistant.mMinContLength,
                                                            _mAssistant.mMaxMarkDiam,
                                                            out _mMarkCenterCols,
                                                            out _mEstimatedPose);


                _mMarkCenter.GenCrossContourXld(_mMarkCenterRows,
                                                _mMarkCenterCols,
                                                new HTuple(6.0),
                                                0.785398);

                if (failed)
                {
                    _mAssistant.addQualityIssue(this, CalibrationAssistant.QUALITY_ISSUE_FAILURE, 0.0);
                }


                HOperatorSet.ImagePointsToWorldPlane(startCamp, _mEstimatedPose,
                                                     _mMarkCenterRows, _mMarkCenterCols,
                                                     unit, out worldX, out worldY);
                _mEstimatedPlateSize = HMisc.DistancePp(worldY[0].D, worldX[0].D,
                                                        worldY[1].D, worldX[1].D);
                _mEstimatedPlateSize *= 10.0;
                proc.get_3d_coord_system(_mImage, out _mEstimatedWCS,
                                         startCamp, _mEstimatedPose,
                                         new HTuple(_mEstimatedPlateSize / 2.0));

                PlateStatus  = _mQualityIssuesList.Count > 0 ? CalibrationAssistant.PS_QUALITY_ISSUES : CalibrationAssistant.PS_OK;                // "Quality Issues found": "OK";
                CanCalibFlag = 0;
            }
            catch (HOperatorException e)
            {
                this.ErrorMessage = e.Message;
                CanCalibFlag      = 1;

                /* if exception was raised due to lack of memory,
                 * forward the error to the calling method */
                if (e.Message.IndexOf("not enough") != -1)
                {
                    throw (e);
                }
            }
        }
        /// <summary>
        /// Tests different quality features for the calibration image 
        /// <c>cImg</c>
        /// </summary>
        /// <returns>
        /// Returns a value indicating the success or failure
        /// of the quality assessment
        /// </returns>
        public bool testQualityIssues(CalibImage cImg)
        {
            ArrayList qList;

            HObject markContours;
            HObject plateRegion;
            HImage mImg;
            HTuple score, score2, contrast;
            int numRegions, numContours;
            bool qualityFailure;

            mImg = cImg.GetImage();
            qList = cImg.GetQualityIssueList();
            procedure = new QualityProcedures();
            contrast = new HTuple();
            qualityFailure = false;
            // DescriptionFileName = mDescrFileName;
            ;

            try
            {
                procedure.find_caltab_edges(mImg, out plateRegion,
                                            out markContours,
                                            new HTuple(mDescrFileName));
                numRegions = plateRegion.CountObj();
                numContours = markContours.CountObj();

                if (mImageTests < QUALITY_ISSUE_TEST_NONE)
                {
                    if (numRegions == 0)
                    {
                        qualityFailure = true;
                    }
                    else
                    {
                        procedure.eval_caltab_overexposure(mImg, plateRegion, out score);
                        addQualityIssue(qList, QUALITY_ISSUE_IMG_EXPOSURE, score.D);
                    }

                    if (numContours == 0)
                    {
                        qualityFailure = true;
                    }
                    else
                    {
                        procedure.eval_caltab_contrast_homogeneity(mImg, markContours, out contrast, out score, out score2);
                        addQualityIssue(qList, QUALITY_ISSUE_IMG_CONTRAST, score.D);
                        addQualityIssue(qList, QUALITY_ISSUE_IMG_HOMOGENEITY, score2.D);

                        procedure.eval_caltab_size(mImg, plateRegion, markContours, out score);
                        addQualityIssue(qList, QUALITY_ISSUE_IMG_CALTAB_SIZE, score.D);
                    }

                    if (mImageTests == QUALITY_ISSUE_TEST_ALL)
                    {
                        procedure.eval_caltab_focus(mImg, markContours, contrast, out score);
                        addQualityIssue(qList, QUALITY_ISSUE_IMG_FOCUS, score.D);
                    }
                }
            }
            catch (HOperatorException e)
            {
                throw (e);
            }

            return qualityFailure;
        }
        /// <summary>
        /// Determine s(or updates) the basic information for this 
        /// calibration image, which are the values for the region 
        /// plate, the center marks, and the estimated pose. 
        /// The flag <c>mPlateStatus</c> describes the evaluation 
        /// of the computation process.
        /// If desired the quality assessment can be recalculated 
        /// as well.
        /// </summary>
        /// <param name="updateQuality">
        /// Triggers the recalculation of the quality assessment for
        /// this calibration image 
        /// </param>
        public void UpdateCaltab(bool updateQuality)
        {
            HTuple worldX, worldY;
            HTuple unit = new HTuple("m");

            bool failed = false;
            QualityProcedures proc = new QualityProcedures();
            string descrFile;
            HTuple startCamp;
            ErrorMessage = "";

            _mCaltabRegion.Dispose();
            _mMarkCenter.Dispose();
            _mEstimatedWCS.Dispose();

            //reset this variable
            _mMarkCenterRows = new HTuple();

            PlateStatus = CalibrationAssistant.PS_NOT_FOUND;

            descrFile = _mAssistant.getDesrcFile();

            try
            {
                _mCaltabRegion = _mImage.FindCaltab(descrFile,
                                                 (int)_mAssistant.mFilterSize,
                                                 (int)_mAssistant.mMarkThresh,
                                                 (int)_mAssistant.mMinMarkDiam);

                PlateStatus = CalibrationAssistant.PS_MARKS_FAILED;

                //-- Quality issue measurements --
                if (updateQuality)
                {
                    _mQualityIssuesList.Clear();
                    failed = _mAssistant.testQualityIssues(this);
                }

                startCamp = _mAssistant.getCameraParams(this);
                _mMarkCenterRows = _mImage.FindMarksAndPose(_mCaltabRegion,
                                                          descrFile,
                                                          startCamp,
                                                          (int)_mAssistant.mInitThresh,
                                                          (int)_mAssistant.mThreshDecr,
                                                          (int)_mAssistant.mMinThresh,
                                                          _mAssistant.mSmoothing,
                                                          _mAssistant.mMinContLength,
                                                          _mAssistant.mMaxMarkDiam,
                                                          out _mMarkCenterCols,
                                                          out _mEstimatedPose);

                _mMarkCenter.GenCrossContourXld(_mMarkCenterRows,
                                               _mMarkCenterCols,
                                               new HTuple(6.0),
                                               0.785398);

                if (failed)
                    _mAssistant.addQualityIssue(this, CalibrationAssistant.QUALITY_ISSUE_FAILURE, 0.0);

                HOperatorSet.ImagePointsToWorldPlane(startCamp, _mEstimatedPose,
                                                     _mMarkCenterRows, _mMarkCenterCols,
                                                     unit, out worldX, out worldY);
                _mEstimatedPlateSize = HMisc.DistancePp(worldY[0].D, worldX[0].D,
                                                       worldY[1].D, worldX[1].D);
                _mEstimatedPlateSize *= 10.0;
                proc.get_3d_coord_system(_mImage, out _mEstimatedWCS,
                                         startCamp, _mEstimatedPose,
                                         new HTuple(_mEstimatedPlateSize / 2.0));

                PlateStatus = _mQualityIssuesList.Count > 0 ? CalibrationAssistant.PS_QUALITY_ISSUES : CalibrationAssistant.PS_OK; // "Quality Issues found": "OK";
                CanCalibFlag = 0;
            }
            catch (HOperatorException e)
            {
                this.ErrorMessage = e.Message;
                CanCalibFlag = 1;

                /* if exception was raised due to lack of memory,
                 * forward the error to the calling method */
                if (e.Message.IndexOf("not enough") != -1)
                    throw (e);
            }
        }