using System;
using HalconDotNet;
using System.Collections;
namespace HalconTools
{
public delegate void MeasureDelegate(int value);
///
/// The controller class MeasureAssistant controls
/// the communication between the GUI and the model data that
/// is used to parameterize the measuring.
///
public class MeasureAssistant
{
/// Index of the selected ROI.
public int mActRoiIdx;
/// Reference to the ROI controller instance.
private ROIController roiController;
/// List of measure handles created for the list of ROIs.
private ArrayList mMeasureList;
/// Reference to list of ROI instances.
private ArrayList mROIList;
/// HALCON image used for measuring.
public HImage mImage;
public int mWidth;
public int mHeight;
/// Flag indicating whether measurements are performed between
/// individual edges or edge pairs.
public bool mSelPair;
/// Minimum edge amplitude.
public double mThresh;
/// Sigma of Gaussian smoothing.
public double mSigma;
///
/// Width of the measure ROI (circular ROI: radius (half width) of the
/// annulus; linear ROI: half height of the rectangle).
///
public double mRoiWidth;
public double mRoiHeight;
/// Default value for the minimum edge amplitude.
public double mInitThresh;
/// Default value for the sigma of Gaussian smoothing.
public double mInitSigma;
/// Default value for the ROI width.
public double mInitRoiWidth;
///
/// Type of gray-value transition; determines how edges are
/// selected (dark-light or light-dark transition).
///
public string mTransition;
/// Position of edges to select.
public string mPosition;
/// Type of interpolation to be used.
public string mInterpolation;
///
/// Length of the displayed edges.
///
public int mDispEdgeLength;
/// Error messages for failed measure actions.
public HTuple exceptionText;
///
/// Flag indicating whether files with internal camera parameters
/// and camera pose are present and valid.
///
public bool mIsCalibValid;
///
/// Flag indicating whether measure results should be transformed
/// into world coordinates.
///
public bool mTransWorldCoord;
///
/// Flag indicating whether the ROI width should be used for
/// displaying the extracted edges (instead of mDispEdgeLength).
///
public bool mDispROIWidth;
///
/// Flag to add position coordinates of the detected (and
/// selected) edges to the result table.
///
public bool mDispPosition;
///
/// Flag to add the pair width of the detected edge (and
/// selected) pairs to the result table.
///
public bool mDispPairWidth;
///
/// Flag to add the edge amplitude of the detected (and
/// selected) edge pairs to the result table.
///
public bool mDispAmplitude;
///
/// Flag to add the distance between consecutive detected (and
/// selected) edges to the result table.
///
public bool mDispDistance;
/// File with internal camera parameters.
public HTuple mCamParameter;
/// Camera pose file.
public HTuple mCamPose;
/// Unit for transformation into world coordinates.
public string mUnit;
/// Constant indicating an update of measure instances.
public const int EVENT_UPDATE_MEASUREMENT = 2;
///
/// Constant indicating the removal of measure instances from the
/// measure list mMeasureList.
///
public const int EVENT_UPDATE_REMOVE = 3;
/// Constant indicating an update of measure results.
public const int EVENT_UPDATE_RESULT_XLD = 4;
/// Auxiliary constant.
public const int ALL_ROI =-1;
///
/// Constant indicating an error while reading an image file.
public const int ERR_READING_FILE = 10;
public MeasureDelegate NotifyMeasureObserver;
/* To create the measure controller class the ROI
controller has to be provided for initialization */
public MeasureAssistant(ROIController CRoi)
{
exceptionText = "";
roiController = CRoi;
mROIList = roiController.getROIList();
mMeasureList = new ArrayList(15);
mIsCalibValid = false;
mActRoiIdx = -1;
}
/*********************************************************/
/* setter-methods */
/*********************************************************/
///
/// Sets a flag to determine if measure detection is calculated
/// for edges or edge pairs
///
public void setSelPair(bool mode)
{
mSelPair = mode;
UpdateMeasure();
mActRoiIdx = roiController.getActiveROIIdx();
}
///
/// Sets the variable mThresh to the provided value and
/// triggers an update for the measure results
///
public void setMinEdgeAmpl(double val)
{
mThresh = val;
UpdateExecute(ALL_ROI);
}
///
/// Sets the variable mSigma to the provided value and
/// triggers an update for the measure results
///
public void setSigma(double val)
{
mSigma = val;
UpdateExecute(ALL_ROI);
}
///
/// Sets the variable mRoiWidth to the provided value and
/// triggers an update for the measure results
///
public void setRoiWidth(double val)
{
mRoiWidth = val;
UpdateMeasure(ALL_ROI);
}
public void setRoiHeight(double val)
{
mRoiHeight = val;
UpdateMeasure(ALL_ROI);
}
///
/// Sets the variable mInterpolation to the provided value and
/// triggers an update for the measure results
///
public void setInterpolation(string mode)
{
mInterpolation = mode;
UpdateMeasure(ALL_ROI);
}
///
/// Sets the variable mTransition to the provided value and
/// triggers an update for the measure results
///
public void setTransition(string mode)
{
mTransition = mode;
UpdateExecute(ALL_ROI);
}
///
/// Sets the position of edges to select to the provided value and
/// triggers an update od the measure results.
///
public void setPosition(string mode)
{
mPosition = mode;
UpdateExecute(ALL_ROI);
}
///
/// Sets the length of the displayed edges to the provided value
/// and triggers an update of the measure results.
///
public void setDispEdgeLength(int val)
{
mDispEdgeLength = val;
UpdateXLD();
}
///
/// Sets the width of the displayed ROI to the provided value
/// and triggers an update for the measure results
///
public void setFlagDispROIWidth(bool mode)
{
mDispROIWidth = mode;
UpdateXLD();
}
/********************************************************/
/* determine list of result coordinates to be displayed */
/********************************************************/
///
/// Sets a flag to determine if the edge positions of
/// measure results are added and displayed on the
/// measure result table
///
public void showPosition(bool mode)
{
mDispPosition = mode;
}
///
/// Sets a flag to determine if the intra distance for
/// measure edge pairs are added and displayed on the
/// measure result table
///
public void showPairWidth(bool mode)
{
mDispPairWidth = mode;
}
///
/// Sets a flag to determine if the edge amplitude of
/// measure results are added and displayed on the
/// measure result table
///
public void showAmplitude(bool mode)
{
mDispAmplitude = mode;
}
///
/// Sets a flag to determine if the edge distance of
/// measure results are added and displayed on the
/// measure result table
///
public void showDistance(bool mode)
{
mDispDistance = mode;
}
///
/// Sets the unit for world coordinate transformation to
/// the provided value and triggers an update of the
/// measure results
///
public void setUnit(string val)
{
mUnit = val;
UpdateExecute(ALL_ROI);
}
///
/// Sets the variable mTransWorldCoord to the provided
/// value and triggers an update for the measure results
///
public void setTransWorldCoord(bool mode)
{
mTransWorldCoord = mode;
UpdateExecute(ALL_ROI);
}
///
/// Load an HALCON image from the file filename and
/// delete the list of measure handles created for the
/// previous image setup
///
/// Location of image file
/// Flag depicting success of the load process
public bool setImage(string filename)
{
string tmp;
RemoveAllMeasureObjects();
exceptionText = "";
try
{
mImage = new HImage(filename);
mImage.GetImagePointer1(out tmp, out mWidth, out mHeight);
}
catch (HOperatorException e)
{
mImage = null;
exceptionText = e.Message;
NotifyMeasureObserver(MeasureAssistant.ERR_READING_FILE);
return false;
}
return true;
}
///
/// Sets the variable mImage to the HImage provided
///
/// HALCON image instance
public void setImage(HImage img)
{
string tmp;
RemoveAllMeasureObjects();
mImage = img;
if (mImage != null)
mImage.GetImagePointer1(out tmp, out mWidth, out mHeight);
}
///
/// Returns the image currently used for measurement, described
/// by mImage
///
public HImage getImage()
{
return mImage;
}
/// Load camera calibration data from file
/// Location of *.cal file
public void LoadCamParFile(string file)
{
exceptionText = "";
try
{
mCamParameter = null;
mCamParameter = HMisc.ReadCamPar(file);
}
catch (HOperatorException e)
{
mIsCalibValid = false;
exceptionText = e.Message;
throw (e);
}
if (mCamParameter == null || !(mCamParameter.Length > 0) || mCamPose == null || !(mCamPose.Length > 0))
mIsCalibValid = false;
else
mIsCalibValid = true;
if (mIsCalibValid)
UpdateExecute(ALL_ROI);
}
/// Load camera pose data from file
/// Location of *.dat file
public void LoadCamPoseFile(string file)
{
exceptionText = "";
try
{
HOperatorSet.ReadPose(new HTuple(file), out mCamPose);
}
catch (HOperatorException e)
{
mIsCalibValid = false;
exceptionText = e.Message;
throw (e);
}
if (mCamParameter == null || !(mCamParameter.Length > 0) || mCamPose == null || !(mCamPose.Length > 0))
mIsCalibValid = false;
else
mIsCalibValid = true;
if (mIsCalibValid)
UpdateExecute(ALL_ROI);
}
///
/// Create a measure object for the new instance of an interactive
/// ROI at index mActRoiIdx
///
public void AddMeasureObject()
{
mActRoiIdx = roiController.getActiveROIIdx();
if (mActRoiIdx != -1)
mMeasureList.Add(CreateMeasure((ROI)mROIList[mActRoiIdx], this));
NotifyMeasureObserver(EVENT_UPDATE_MEASUREMENT);
}
///
/// Update measure object for the selected interactive ROI
/// at index or update measure handles for the
/// entire set of interactive ROIs
///
public void UpdateMeasure(int index)
{
if (index == -1)
{
for (int i =0; i < mMeasureList.Count; i++)
((Measurement)mMeasureList[i]).UpdateROI();
}
else
{
((Measurement)mMeasureList[index]).UpdateROI();
}
NotifyMeasureObserver(EVENT_UPDATE_MEASUREMENT);
}
///
/// Recreate the entire measure object list, if the
/// measure edge type changes from edge pose to
/// edge pairs or vice versa
///
public void UpdateMeasure()
{
RemoveAllMeasureObjects();
for (int i =0; i < mROIList.Count; i++)
{
ROI roi = (ROI)mROIList[i];
mMeasureList.Add(CreateMeasure((ROI)mROIList[i], this));
}
NotifyMeasureObserver(EVENT_UPDATE_MEASUREMENT);
}
///
/// Update measure results for a selected measure object instance
/// at index or the entire set of measure handles.
///
public void UpdateExecute(int index)
{
if (index == -1)
{
for (int i =0; i < mMeasureList.Count; i++)
((Measurement)mMeasureList[i]).UpdateResults();
}
else
{
((Measurement)mMeasureList[index]).UpdateResults();
}
NotifyMeasureObserver(EVENT_UPDATE_MEASUREMENT);
}
///
/// Update display objects of the measure results
/// for the entire set of measure handles
///
public void UpdateXLD()
{
for (int i =0; i < mMeasureList.Count; i++)
((Measurement)mMeasureList[i]).UpdateXLD();
NotifyMeasureObserver(EVENT_UPDATE_RESULT_XLD);
}
///
/// Clear the entire list of measure handles and
/// releases the resources used
///
public void RemoveAllMeasureObjects()
{
int count = mMeasureList.Count;
for (int i=0; i < count; i++)
RemoveMeasureObjectIdx(0);
NotifyMeasureObserver(EVENT_UPDATE_REMOVE);
}
///
/// Clear the measure object corresponding to the deleted
/// interactive ROI and release the resources used
///
public void RemoveMeasureObjectActIdx()
{
int DelIdx = roiController.getDelROIIdx();
RemoveMeasureObjectIdx(DelIdx);
NotifyMeasureObserver(EVENT_UPDATE_REMOVE);
}
///
/// Clear the measure object at the index DelIdx from
/// the measure object list and release the resources used
///
private void RemoveMeasureObjectIdx(int DelIdx)
{
Measurement m = (Measurement)mMeasureList[DelIdx];
mMeasureList.RemoveAt(DelIdx);
m.ClearMeasurement();
mActRoiIdx = -1;
}
///
/// Factory method to create measure objects
///
/// Interactive ROI
///
/// Reference to measure controller class
///
/// New measure object
public static Measurement CreateMeasure(ROI roi, MeasureAssistant parent)
{
if (parent.mSelPair)
return new MeasurementPair(roi, parent);
else
return new MeasurementEdge(roi, parent);
}
///
/// Composes set of HALCON iconic objects to display
/// measure edge results
///
/// Detected measure edges
public HXLDCont getMeasureResults()
{
HXLDCont val;
HXLDCont obj = new HXLDCont();
obj.GenEmptyObj();
for (int i=0; i < mMeasureList.Count; i++)
{
val = ((Measurement)mMeasureList[i]).getMeasureResults();
if (val.IsInitialized())
obj = obj.ConcatObj(val);
}
return obj;
}
///
/// Composes set of HALCON iconic objects to display
/// dimension of measure object
///
/// Surrounding contour of measure object
public HObject getMeasureRegions()
{
HObject val;
HObject obj = new HObject();
obj.GenEmptyObj();
for (int i=0; i < mMeasureList.Count; i++)
{
val = ((Measurement)mMeasureList[i]).getMeasureRegion();
if (val.IsInitialized())
obj = obj.ConcatObj(val);
}
return obj;
}
/// Returns number of measure objects
/// Length of mMeasureList
public int getMeasureListCount()
{
return mMeasureList.Count;
}
/// Change index for selected interactive ROI
public void ClickedActiveROI()
{
mActRoiIdx = roiController.getActiveROIIdx();
}
///
/// Compose set of measure result data to display in the result table
///
/// Composition of measure result information
public ArrayList getMeasureTableData()
{
MeasureResult resultData;
ArrayList table = new ArrayList(10);
if (mMeasureList.Count == 0 || mActRoiIdx == -1)
return table;
resultData = ((Measurement)mMeasureList[mActRoiIdx]).getMeasureResultData();
if (mSelPair)
{
if (mDispPosition)
{
table.Add(((PairResult)resultData).rowEdgeFirst);
table.Add(((PairResult)resultData).colEdgeFirst);
table.Add(((PairResult)resultData).rowEdgeSecond);
table.Add(((PairResult)resultData).colEdgeSecond);
}
if (mDispAmplitude)
{
table.Add(((PairResult)resultData).amplitudeFirst);
table.Add(((PairResult)resultData).amplitudeSecond);
}
if (mDispDistance)
table.Add(((PairResult)resultData).interDistance);
if (mDispPairWidth)
table.Add(((PairResult)resultData).intraDistance);
}
else
{
if (mDispPosition)
{
table.Add(((EdgeResult)resultData).rowEdge);
table.Add(((EdgeResult)resultData).colEdge);
}
if (mDispAmplitude)
table.Add(((EdgeResult)resultData).amplitude);
if (mDispDistance)
table.Add(((EdgeResult)resultData).distance);
}
return table;
}
///
/// Compose the set of measure result types to be displayed
/// in the result table. The types are determined by the user,
/// who can check the corresponding flags in the GUI frontend
///
/// Composition of measure result types
public ArrayList getMeasureResultComposition()
{
ArrayList composition = new ArrayList(5);
if (mSelPair)
{
if (mDispPosition)
{
composition.Add("Row 1st");
composition.Add("Col 1st");
composition.Add("Row 2nd");
composition.Add("Col 2nd");
}
if (mDispAmplitude)
{
composition.Add("Amplitude 1st");
composition.Add("Amplitude 2nd");
}
if (mDispDistance)
composition.Add("Distance");
if (mDispPairWidth)
composition.Add("Width");
}
else
{
if (mDispPosition)
{
composition.Add("Row");
composition.Add("Column");
}
if (mDispAmplitude)
composition.Add("Amplitude");
if (mDispDistance)
composition.Add("Distance");
}
return composition;
}
///
/// Determine the gray value projection for the measure object
/// corresponding to the interactive ROI currently selected.
/// If no ROI is selected then return a null-object.
///
/// Gray value profile
public double[] getMeasureProjection()
{
if (mActRoiIdx == -1)
return null;
else
return ((Measurement)mMeasureList[mActRoiIdx]).getGrayValueProj();
}
}//end of class
}//end of namespace