Edge Position 8

Overview

The mechanism of "Inner unit" enables creating new processing item by combining existing processing items.
This example shows the way to create new processing item with eight regions, using "Edge Position" item as inner unit.

Specification

Setting screen
This is same as standard Edge Position processing item. However the box for selecting region is added.

Figure setting


Edge Color


Reference Position


Measurement

Measurement
Execute measurement for all configured edge regions.
External reference data
The external reference data of this item are designed, that all the external reference data of inner units can be referred or modified via external reference data of this item.
External reference by number is defined as (region number + 1) * 200 + (external reference number of Edge Position item).
However external reference number 0 is a total judgement result of this item.
200 - 399
Region 0
400 - 599
Region 1
600 - 799
Region 2
800 - 999
Region 3
1000 - 1199
Region 4
1200 - 1399
Region 5
1400 - 1599
Region 6
1600 - 1799
Region 7
Also, external reference string is defined as RNXXXX (N: Region number, XXXX:external reference string of Edge Position item).
This is part of the external reference of this item.
Number
String
Data
Set/Get
Range
0
JG
judge
Total judgement result
Get only
0: No judgement (unmeasured)
1: Judgement result OK
-1: Judgement result NG
-10: Error (image)
-11: Error (model)
-12: Error (memory)
-20:Error (other error)
200
R0JG
R0judge
Region 0 Judgement result
Get only
0: No judgement (unmeasured)
1: Judgement result OK
-1: Judgement result NG
-10: Error (image)
-11: Error (model)
-12: Error (memory)
-20:Error (other error)
205
R0X
R0positionX
Region 0 Edge position X
Get only
0 - 99999.9999
206
R0Y
R0positionY
Region 0 Edge position Y
Get only
0 - 99999.9999
207
R0SX
R0referenceX
Region 0 Reference position X
Get only
0 - 99999.9999
208
R0SY
R0referenceY
Region 0 Reference position Y
Get only
0 - 99999.9999
301
R0outputCoordinate
Region 0 Output coordinates
Set/Get
0:After scroll
1:Before scroll
302
R0calibration
Region 0 Calibration
Set/Get
0:OFF, 1:ON
320
R0colorSpecification
Region 0 Edge color specification
Set/Get
0:OFF, 1:ON
321
R0colorR
Region 0 Edge color R
Set/Get
0 - 255
322
R0colorG
Region 0 Edge color G
Set/Get
0 - 255
323
R0colorB
Region 0 Edge color B
Set/Get
0 - 255
(abbreviated)
400
R1JG
R1judge
Region 1 Judgement result
Get only
0: No judgement (unmeasured)
1: Judgement result OK
-1: Judgement result NG
-10: Error (image)
-11: Error (model)
-12: Error (memory)
-20:Error (other error)
405
R1X
R1positionX
Region 1 Edge position X
Get only
0 - 99999.9999
(abbreviated)
Display image
Sub image number
Image
-1(Positions)
All edge regions and positions
0
All edge regions and positions
1
Detailed display of Region 0
2
Detailed display of Region 1
3
Detailed display of Region 2
4
Detailed display of Region 3
5
Detailed display of Region 4
6
Detailed display of Region 5
7
Detailed display of Region 6
8
Detailed display of Region 7

Implementation

1.Creating project
Create project according to tutorial refcreating project.
The parameters are as below.
Application Template
Measure Process item
Identification name (Project name)
Edge Postion 8
After creation of the project, Visual Studio 2008 opens the project file.
2.Assining inner units
When the unit of this item is added to the flow, assing inner units for making them ready to use.
Use refProcUnit::AssingInnerUnit to assign inner units.

AssignProc.cpp
int CLASSNAME::AssignProc(ProcUnit *ptrProcUnit)
{
        for (int i = 0; i < 8; i++) {
                if (NORMAL != ptrProcUnit->AssignInnerUnit(i,  _T("EdgePosition"))) {
                        return -1;
                }
        }
        return(NORMAL);
}

3.Referring and Setting Figure data of inner units
It is not possible to manipulate figure data of innter unit directly from setting screen.
Therefore, it is required to convert the figure number of this item to inner unit number.
Figure number
of this item
Inner unit
number
Figure number
of inner unit
0
0
0 (Edge measurement region)
1
1
0 (Edge measurement region)
2
2
0 (Edge measurement region)
3
3
0 (Edge measurement region)
4
4
0 (Edge measurement region)
5
5
0 (Edge measurement region)
6
6
0 (Edge measurement region)
7
7
0 (Edge measurement region)
8
0
1 (Area for color extraction)
And get the innier unit with refProcUnit::GetInnerUnit and call APIs of refProcUnit::SetFigureType, refProcUnit::GetFigureType, refProcUnit::AddFigureData and refProcUnit::GetFigureData.


FigureData.cpp
int CLASSNAME::SetFigureType(ProcUnit *ptrProcUnit, int figureNo, int type)
{
        int     unitNo;

        if (figureNo >= 0 && figureNo < 8) {
                unitNo = figureNo;
                figureNo = 0;
        } else if (figureNo == 8) {

                // get color data
                unitNo = 0;
                figureNo = 1;
        }

        if (ptrProcUnit->CheckInnerUnit(unitNo) != TRUE) {
                return -1;
        }

        ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(unitNo);
        return(ProcItem::SetFigureType(targetUnit, figureNo, type));
}

int CLASSNAME::GetFigureType(ProcUnit *ptrProcUnit, int figureNo)
{
        int     unitNo;

        if (figureNo >= 0 && figureNo < 8) {
                unitNo = figureNo;
                figureNo = 0;
        } else if (figureNo == 8) {

                // get color data
                unitNo = 0;
                figureNo = 1;
        }

        if (ptrProcUnit->CheckInnerUnit(unitNo) != TRUE) {
                return -1;
        }

        ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(unitNo);
        return(ProcItem::GetFigureType(targetUnit, figureNo));
}

int CLASSNAME::SetFigureData(ProcUnit *ptrProcUnit, int figureNo, FIG_HEADER *ptrFigure)
{
        int     unitNo;

        if (figureNo >= 0 && figureNo < 8) {
                unitNo = figureNo;
                figureNo = 0;
        } else if (figureNo == 8) {

                // get color data
                unitNo = 0;
                figureNo = 1;
        }

        if (ptrProcUnit->CheckInnerUnit(unitNo) != TRUE) {
                return -1;
        }

        ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(unitNo);

        int res = targetUnit->SetFigureData(figureNo, ptrFigure, 1);
        return res;
}

int CLASSNAME::AddFigureData(ProcUnit *ptrProcUnit, int figureNo, FIG_TYPE *type, void *data)
{
        int     unitNo;

        if (figureNo >= 0 && figureNo < 8) {
                unitNo = figureNo;
                figureNo = 0;
        } else if (figureNo == 8) {

                // get color data
                unitNo = 0;
                figureNo = 1;
        }

        if (ptrProcUnit->CheckInnerUnit(unitNo) != TRUE) {
                return -1;
        }

        ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(unitNo);
        return(ProcItem::AddFigureData(targetUnit, figureNo, type, data));
}

FIG_HEADER *CLASSNAME::GetFigureData(ProcUnit *ptrProcUnit, int figureNo)
{
        int     unitNo;

        if (figureNo >= 0 && figureNo < 8) {
                unitNo = figureNo;
                figureNo = 0;
        } else if (figureNo == 8) {

                // get color data
                unitNo = 0;
                figureNo = 1;
        }

        if (ptrProcUnit->CheckInnerUnit(unitNo) != TRUE) {
                return NULL;
        }

        ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(unitNo);
        return(ProcItem::GetFigureData(targetUnit, figureNo));
}

4.Measurement initialization and measurement procedure of inner units
In order to execute measurement of inner units, it is necessary to call mesurement initalization and measurement procedure of inner units on the timing of measurement initialization and measuremnet procedure of processing item.
To do so, call refProcUnit::MeasureInit and refProcUnit::MeasureProc for the inner unit acquired with refProcUnit::GetInnerUnit API.
It is also necessary to implement to set total judge result of this item.

MeasureInit.cpp
int CLASSNAME::MeasureInit(ProcUnit *ptrProcUnit)
{
        for (int i = 0; i < 8; i++) {
                if (ptrProcUnit->CheckInnerUnit(i) != TRUE) {
                        return -1;
                }
                ProcUnit *ptrInnerUnit = ptrProcUnit->GetInnerUnit(i);
        }
        return(NORMAL);
}


MeasureProc.cpp
int CLASSNAME::MeasureProc(ProcUnit *ptrProcUnit)
{
        int     judge = JUDGE_OK;

        SETUPDATA *ptrSetupData = ptrProcUnit->GetSetupData();
        MEASUREDATA *ptrMeasureData = ptrProcUnit->GetMeasureData();

        int meascount = 0;
        for (int i = 0; i < 8; i++) {
                ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(i);
                FIG_HEADER *figData = targetUnit->GetFigureData(0);

                if (figData == NULL) {  // model is not registered
                        targetUnit->SetUnitJudge(JUDGE_NC, FALSE);                   
                } else {
                        targetUnit->MeasureProc();
                        meascount++;
                }

                ptrMeasureData->judgeInnerUnit[i] = targetUnit->GetUnitJudge();
                if (ptrMeasureData->judgeInnerUnit[i] != JUDGE_OK && 
                        ptrMeasureData->judgeInnerUnit[i] != JUDGE_NC) {
                        judge = ptrMeasureData->judgeInnerUnit[i];
                }
        }
        if (meascount == 0) {
                judge = JUDGE_NG;
        }

        ptrProcUnit->SetUnitJudge(judge, FALSE);

        return(NORMAL);
}

5.Display prodecure of inner units
In order to show the image and graphic display on setting and measurement screen, at first convert sub inage number to inner unit number and sub image number of inner unit, and call display function of inner unit.
Display for setting
Sub image number
Display
0
(Only input image)
1
Sub image 1 (Edge projection) of inner unit 0
2
Sub image 1 (Edge projection) of inner unit 1
3
Sub image 1 (Edge projection) of inner unit 2
4
Sub image 1 (Edge projection) of inner unit 3
5
Sub image 1 (Edge projection) of inner unit 4
6
Sub image 1 (Edge projection) of inner unit 5
7
Sub image 1 (Edge projection) of inner unit 6
8
Sub image 1 (Edge projection) of inner unit 7

SetupDisp.cpp
int CLASSNAME::SetupDisp(ProcUnit *ptrProcUnit, int subNo, ImageWindow *ptrImageWindow)
{
        IMAGE           *image = ptrProcUnit->GetMeasureImage(0);

        ptrImageWindow->ImageDisp(image);

        if (subNo > 0 && subNo <= 8) {
                ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(subNo - 1);
                targetUnit->SetupDisp(1, ptrImageWindow);
        }

        return(NORMAL);
}

Display for measurement
Sub image number
Display
0
(Only input image)
1
Sub image 1 (Edge projection) of inner unit 0
2
Sub image 1 (Edge projection) of inner unit 1
3
Sub image 1 (Edge projection) of inner unit 2
4
Sub image 1 (Edge projection) of inner unit 3
5
Sub image 1 (Edge projection) of inner unit 4
6
Sub image 1 (Edge projection) of inner unit 5
7
Sub image 1 (Edge projection) of inner unit 6
8
Sub image 1 (Edge projection) of inner unit 7

MeasureDisp.cpp
int CLASSNAME::MeasureDispI(ProcUnit *ptrProcUnit, int subNo, ImageWindow *ptrImageWindow)
{

        if (subNo > 0 && subNo <= 8) {
                ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(subNo - 1);
                targetUnit->MeasureDispI(1, ptrImageWindow);
        } else {
                IMAGE           *image = ptrProcUnit->GetMeasureImage(0);
                ptrImageWindow->ImageDisp(image);
        }

        return(NORMAL);
}

int CLASSNAME::MeasureDispG(ProcUnit *ptrProcUnit, int subNo, ImageWindow *ptrImageWindow)
{
        if (subNo == 0) {

                // display all regions
                for (int i = 0; i < 8; i++) {
                        ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(i);
                        targetUnit->MeasureDispG(0, ptrImageWindow);
                }
        }

        return(NORMAL);
}

int CLASSNAME::MeasureDispT(ProcUnit *ptrProcUnit, int subNo, TextWindow *ptrTextWindow)
{
        MEASUREDATA *ptrMeasureData = ptrProcUnit->GetMeasureData();

        int nJudge = ptrProcUnit->GetUnitJudge();

        ptrTextWindow->DrawJudgeText(nJudge);

        if (nJudge != JUDGE_NC) {

                ptrProcUnit->SetMeasureProcMask(1);

                for (int i = 0; i < 8; i++) {
                        ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(i);
                        ANYTYPE any;
                        targetUnit->GetUnitData(_T("positionX"), &any);
                        ptrMeasureData->coPos[i].x = any.dval;
                        
                        targetUnit->GetUnitData(_T("positionY"), &any);
                        ptrMeasureData->coPos[i].y = any.dval;       
                        
                        nJudge = targetUnit->GetUnitJudge();
                        ptrTextWindow->DrawTextW(nJudge, TRUE, _T("Edge %d  x:%.2f, y:%.2f"), i, ptrMeasureData->coPos[i].x, ptrMeasureData->coPos[i].y);
                }
                ptrProcUnit->SetMeasureProcMask(0);
        }

        return(NORMAL);
}


6.External reference data
Convert original external reference number or string to inner unit number and external reference of inner unit, and call
refProcUnit::GetUnitData or refProcUnit::SetUnitData for inner units.

UnitData.cpp
static const TCHAR *regionPrefix[] = {
        _T("R0"),
        _T("R1"),
        _T("R2"),
        _T("R3"),
        _T("R4"),
        _T("R5"),
        _T("R6"),
        _T("R7")
};


int CLASSNAME::SetUnitData(ProcUnit *ptrProcUnit, int dataNo, ANYTYPE *data)
{
        int     res;

        if (dataNo >= 200 && dataNo < 1800) {
            int unitNo = dataNo / 200 - 1;
            dataNo = dataNo - (200 * unitNo) - 200;

                ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(unitNo);
                res = targetUnit->SetUnitData(dataNo, data);
        } else if (dataNo >= 5000) {

                for (int i = 0; i < 7; i++) {

                        ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(i);
                        res = targetUnit->SetUnitData(dataNo, data);
                        if (res != NORMAL) {
                                break;
                        }
                }
        }
        return(NORMAL);
}

int CLASSNAME::SetUnitData(ProcUnit *ptrProcUnit, TCHAR *dataIdent, ANYTYPE *data)
{
        int     res;

        if (_tcslen(dataIdent) > 2) {

                for (int i = 0; i < 8; i++) {
                        if (_tcsncmp(dataIdent, regionPrefix[i], 2) == 0) {
                                                        
                                ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(i);
                                res = targetUnit->SetUnitData(dataIdent+2, data);
                                return res;
                        }
                }
        }

        for (int i = 0; i < 7; i++) {

                ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(i);
                res = targetUnit->SetUnitData(dataIdent, data);
                if (res != NORMAL) {
                        break;
                }
        }
        return(res);
}


int CLASSNAME::GetUnitData(ProcUnit *ptrProcUnit, int dataNo, ANYTYPE *data)
{
        int     res = NORMAL;

        if (dataNo == 0) {
                data->SetVal(ptrProcUnit->GetUnitJudge());

        } else if (dataNo >= 200 && dataNo < 1800) {
            int unitNo = dataNo / 200 - 1;
            dataNo = dataNo - (200 * unitNo) - 200;

                ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(unitNo);
                res = targetUnit->GetUnitData(dataNo, data);

        } else if (dataNo >= 5000) {

                ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(0);
                res = targetUnit->GetUnitData(dataNo, data);
        }
        return(res);
}


int CLASSNAME::GetUnitData(ProcUnit *ptrProcUnit, TCHAR *dataIdent, ANYTYPE *data)
{
        int     res = NORMAL;

        if (_tcscmp(dataIdent, _T("JG")) == 0) {

                data->SetVal(ptrProcUnit->GetUnitJudge());

        } else if (_tcslen(dataIdent) > 2) {

                for (int i = 0; i < 8; i++) {
                        if (_tcsncmp(dataIdent, regionPrefix[i], 2) == 0) {
                                                        
                                ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(i);
                                res = targetUnit->GetUnitData(dataIdent+2, data);
                                return res;
                        }
                }
        }

        ProcUnit *targetUnit = ptrProcUnit->GetInnerUnit(0);
        res = targetUnit->GetUnitData(dataIdent, data);

        return(res);
}


7.Creating setting screen
Following the tutorial of refCreating the Setting Window User Interface (UI) , add tab pages and controls on setting form.

Note
To hide or show tab page according to input image mode, set these value to "Tag" property of tab pages.

COLOR
The tab is shown only when input image is color image.

MONO
The tab is shown only when input image is monochrome image.

Else
The tab is shown in any time.
Add the codes to set "DataIdent" property of each control, according to the value of ValueSetControl (vscRegion) for selecting region number.
For displaying image (imgMain), when Measurement tab (index is 3 or 4) is shown, set the value of region number + 1 as sub image number in order to show projection data of each region.
(Refer to the description of Setting Display)
    Private Sub vscRegion_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles vscRegion.ValueChanged

        setDataIdent()

        Dim index As Integer = Me.tcNormal.SelectedIndex
        If (index = 3 Or index = 4) Then
            Me.imgMain.subNo = vscRegion.Value + 1
        Else
            Me.imgMain.subNo = 0
        End If

    End Sub

    Private Sub setDataIdent()

        figureset.DataIdentNum_Figure = vscRegion.Value

        Me.cbColorSpecification.DataIdent = "R" + CStr(vscRegion.Value) + "colorSpecification"
        Me.colorSet.DataIdent_R = "R" + CStr(vscRegion.Value) + "colorR"
        Me.colorSet.DataIdent_G = "R" + CStr(vscRegion.Value) + "colorG"
        Me.colorSet.DataIdent_B = "R" + CStr(vscRegion.Value) + "colorB"

                ....


For details, check source codes.

Source codes

You can download full set of source codes of this item from this link.
refSource codes