/***************************************************************************/
/*

   Filename:  MilBead.h
   Owner   :  Matrox Imaging
   Revision:  10.60.0776
   Content :  This file contains the defines and the prototypes for the
   MIL bead verifier. (Mbead...)

   Copyright © Matrox Electronic Systems Ltd., 1992-2023.
   All Rights Reserved

*/
/***************************************************************************/
#ifndef __MIL_BEAD_H__
#define __MIL_BEAD_H__

#if (!M_MIL_LITE) // MIL FULL ONLY


/* C++ directive if needed */
#ifdef __cplusplus
extern "C"
{
#endif

   /***************************************************************************/
   /*                        MBead CAPI defines                               */
   /***************************************************************************/
#define M_CONTEXT                                  0x08000000L // Already defined in milmod.h, milreg.h, milstr.h, milocr.h, milcol.h, ...
#define M_GENERAL                                  0x20000000L // Already defined in milmod.h, milreg.h, milstr.h, milocr.h, milcol.h, ...
#define M_ALL                                      0x40000000L // Already defined in milmod.h, milmeas.h, milocr.h,  milpat.h,  mil.h, miledge.h, milcol.h, ...

   // Control Flags for Context
#define M_TRAINING_BOX_WIDTH                       17L         // Width of the search boxes in world units.
#define M_BOX_WIDTH_MARGIN                         2L          // Additional width margin of the search boxes in %.
#define M_TRAINING_BOX_HEIGHT                      3L          // Height of the search boxes in world units.
#define M_TRAINED_BOX_SPACING                      25L         // Readable: inquire the real spacing used for verify operation.
#define M_TRAINING_BOX_SPACING                     40L         // Space between search boxes in world units.
#define M_TRAINING_BOX_INPUT_UNITS                 78L         //
#define M_TEMPLATE_INPUT_UNITS                     79L         //
#define M_SMOOTHNESS                               108L        // Sets the degree of smoothness (strength of denoising), Already defined in milmod.h, milmeas.h, miledge.h, milmetrol.h, mil.h, ...
#define M_TRAINED_WIDTH_NOMINAL                    92L         //
#define M_THRESHOLD_MODE                           33L         // Sets the threshold mode setting, Already defined in milcode.h, miledge.h, milmetrol.h, milstr.h, ...
#define M_THRESHOLD_VALUE                          953L        // Sets the threshold value, Already defined in milcode.h, milstr.h, ...
#define M_FOREGROUND_VALUE                         4L          // Set the color of the bead, Already defined in milblob.h, milcal.h, milcode.h, miledge.h, milmod.h, milocr.h, milstr.h, ...
#define M_WIDTH_NOMINAL                            5L          // Set the nominal width of the bead, Already defined in milmeas.h, milblob,h, ...
#define M_WIDTH_DELTA_NEG                          6L          // Set the delta neg tolerance of the bead's width
#define M_WIDTH_DELTA_POS                          7L          // Set the delta pos tolerance of the bead's width
#define M_OFFSET_MAX                               88L         // Set the max offset tolerance of the bead position relative to the Template, in world units.
#define M_FAIL_WARNING_OFFSET                      99L         // Set the max offset to find the bead position relative to the Template, in world units.
#define M_FOUND_OFFSET_MAX                         M_FAIL_WARNING_OFFSET  // deprecated
#define M_GAP_MAX_LENGTH                           9L          // Set the max valid gap length in world units
#define M_GAP_COVERAGE                             216L        // Retrieve the % of bead found for a Template to be valid
#define M_ACCEPTANCE                               200L        // Set the min % of valid beads for a Template to be valid, Already defined in milmod.h, milpat.h, milreg.h, milcol.h
#define M_ACCURACY                                 106L        // Set the bead verification accuracy level for a Template, Already defined in milmod.h,...
#if OldDefinesSupport
   #define M_ACCURACY_MAX_ANGULAR_DEVIATION        107L
   #define M_ACCURACY_MAX_ANGLE_DEVIATION          107L
   MIL_DEPRECATED(M_ACCURACY_MAX_ANGULAR_DEVIATION, 1010)
   MIL_DEPRECATED(M_ACCURACY_MAX_ANGLE_DEVIATION  , 1010)
#endif
#define M_ANGLE_ACCURACY_MAX_DEVIATION             107L
#define M_WIDTH_NOMINAL_MODE                       12L         // Set the nominal width mode of the bead
#define M_ASSOCIATED_CALIBRATION                   125L        // Set the associated calibration to the training image. // Already defined in milmod.h, milmet.h,...
#define M_CLOSEST_POINT_MAX_DISTANCE               176L        // Set the max distance value for template closest operations
#if OldDefinesSupport
   #define M_GLOBAL_FRAME_OFFSET_X                    1000L
   #define M_GLOBAL_FRAME_OFFSET_Y                    1001L
   #define M_GLOBAL_FRAME_ROTATION                    1002L
   MIL_DEPRECATED(M_GLOBAL_FRAME_OFFSET_X, 1010)
   MIL_DEPRECATED(M_GLOBAL_FRAME_OFFSET_Y, 1010)
   MIL_DEPRECATED(M_GLOBAL_FRAME_ROTATION, 1010)
#endif
#if OldDefinesSupport
   #define M_POSITION_MODE                         1462L       // deprecated flag
   MIL_DEPRECATED(M_POSITION_MODE, 1010)
#endif
#define M_TRAINING_PATH                            1462L
#if OldDefinesSupport
   #define M_TEMPLATE_INDEX_FROM_LABEL             M_INDEX_VALUE // deprecated flag
   MIL_DEPRECATED(M_TEMPLATE_INDEX_FROM_LABEL, 1010)
#endif
#define M_TRAINED_INDIVIDUAL_WIDTH_NOMINAL         207L        //
#define M_TRAINED_SIZE                             209L        //
#define M_TRAINED_POSITION_X                       210L        //
#define M_TRAINED_POSITION_Y                       211L        //
#define M_INDIVIDUAL_WIDTH_NOMINAL                 212L        //

#define M_CIRCLE                                   0x00000008L  // already defined
#define M_TEMPLATE_CIRCLE_CENTER_X                 302L
#define M_TEMPLATE_CIRCLE_CENTER_Y                 303L
#define M_TEMPLATE_CIRCLE_RADIUS                   304L

#define M_SEGMENT                                  0x00000082L  // already defined
#define M_TEMPLATE_SEGMENT_START_X                 305L
#define M_TEMPLATE_SEGMENT_START_Y                 306L
#define M_TEMPLATE_SEGMENT_END_X                   307L
#define M_TEMPLATE_SEGMENT_END_Y                   308L

#define M_POLYLINE_SEED                            444L         // = deprecated M_AUTO
#define M_POLYLINE                                 0x00000020L  // deprecated M_USER_DEFINED

// Control Flags for Context or Result
#if OldDefinesSupport
   #define M_DRAW_RELATIVE_ORIGIN_X                319L        // deprecated : Use MgraControl(... M_DRAW_OFFSET_X...)
   #define M_DRAW_RELATIVE_ORIGIN_Y                320L        // deprecated : Use MgraControl(... M_DRAW_OFFSET_Y...)
   #define M_DRAW_SCALE_X                          3203L       // deprecated : Use MgraControl(... M_DRAW_ZOOM_X ...)
   #define M_DRAW_SCALE_Y                          3204L       // deprecated : Use MgraControl(... M_DRAW_ZOOM_Y ...)
//    MIL_DEPRECATED(M_DRAW_RELATIVE_ORIGIN_X, 1010)              Already defined in mil.h
//    MIL_DEPRECATED(M_DRAW_RELATIVE_ORIGIN_Y, 1010)              Already defined in mil.h
//    MIL_DEPRECATED(M_DRAW_SCALE_X, 1010)                        Already defined in mil.h
//    MIL_DEPRECATED(M_DRAW_SCALE_Y, 1010)                        Already defined in mil.h
#endif
#define M_WORLD                                    0x2000L     // Already defined in milmeas.h,...
#define M_PIXEL                                    0x1000L     // Already defined in milmeas.h,...
#define M_ENHANCED                                 1L

   // Control values 
#define M_USER_DEFINED                             21L         // Already defined in milcal.h, milcode.h, milcolor.h, miledge.h, milmetrol.h, milocr.h, milstr.h, ...
#define M_FOREGROUND_BLACK                         0x100L      // Already defined in    milblob.h, milmod.h,  milcode.h, milocr.h, miledge.h
#define M_FOREGROUND_WHITE                         0x80L       // Already defined in    milblob.h, milmod.h,  milcode.h, milocr.h, miledge.h
#define M_AUTO                                     444L        // Already defined in mil.h, ...
#define M_AUTO_UNIFORM                             M_AUTO
#define M_AUTO_CONTINUOUS                          445
#define M_DISABLE                                 -9999L       // Already defined in milblob.h, milcal.h, milmeas.h, mil.h, ...

   // Strategy Flag

   // Inquire Flags for Context or Result
#define M_MODIFICATION_COUNT                       5010L       // To retrieve the modification counter, Already defined in mil.h, ...
#define M_NUMBER_OF_TEMPLATES                      1L          // To retrieve the number of Template in context or result
#define M_LABEL_VALUE                              1L          // Already defined in mil.h, ...
#define M_INDEX_VALUE                              M_INDEX     // Already defined in mil.h, ...
#define M_SIZE                                     0xC00L      // Retrieve the size of a template. Already defined in milmod, miledge,...
#define M_POSITION_X                               0x00003400L // Already defined in miledge.h, milcode.h, ...
#define M_POSITION_Y                               0x00004400L // Already defined in miledge.h, milcode.h, ...

   // Template function flags
#define M_BEAD_STRIPE                              1L          // Type (stripe) of template to add
#define M_BEAD_EDGE                                2L          // Type (edge) of template to add
#define M_TYPE                                     1008L       // Already defined in mil.h,...
#define M_BEAD_TYPE                                M_TYPE      // Type of the template
#define M_ADD                                      0x0000L     // Add a new Template in the context, Already defined in milcode.h, milim.h, milocr.h, ...
#define M_ADD_FROM_GRAPHIC_LIST                    12L         // Add a new Template in the context from a graphic list primitive (polyline or polygon)
#define M_REPLACE                                  0x01000060L // Already defined in mil.h, milocr.h, miledge.h
#define M_INSERT                                   5L          // Insert points to an existing Template
#define M_DELETE                                   3L          // Delete a Template in the context, Already defined in milblob.h, milcode.h, milcolor.h, miledge.h, milmetrol.h, milmod.h, mil.h, ...
#define M_TRANSLATE_POINTS                         8L          // Move all points of a Template (rigid transformation only)
#define M_SCALE_POINTS                             229L        // Scale all points of a Template
#define M_ROTATE_POINTS                            210L        // Rotate all points of a Template
#define M_SET_WIDTH_NOMINAL                        11L         // To set the width nominal values
#define M_RESET_WIDTH                              0L          // Value to reset the user defined width setting for a specific bead section

   // GetNeighbors function flags
#define M_CLOSEST_TEMPLATE                         11L         // Retrieve closest Templates from a user-defined point
#define M_CLOSEST_POINT                            12L         // Retrieve closest point of a Template from a user-defined point

   // Train operation flag (bitwise)
#define M_SAVE_TRAINING_IMAGE                      2L          // To save the training image into the context
#define M_TRAINING_IMAGE_SIZE_X                    15L         // Size of the training image
#define M_TRAINING_IMAGE_SIZE_Y                    16L         // Size of the training image
#define M_TRAINING_IMAGE_TYPE                      17L         // Type of the training image

   // Context status flag
#define M_COMPLETE                                 0x00000000L // Already defined in mil.h, milmod.h
#define M_PARTIAL                                  0x00000001L // Already defined in mil.h, milmod.h
#define M_NOT_TRAINED                              2L       

   // Result type Flag 
#define M_STATUS                                   0x00008002L // Already defined in milcode.h, milcolor.h, miledge.h, ...
#define M_NUMBER                                   1009L       // Already defined in mil.h, ...
#define M_GAP_TOLERANCE                            216L        // Already defined in milmetrol.h, ...
#define M_WIDTH_MIN                                74L         // 
#define M_WIDTH_MAX                                30L         // 
#define M_WIDTH_AVERAGE                            3L          // 
#define M_POSITION_X                               0x00003400L // Already defined in milmod, milpat.h, ...
#define M_POSITION_Y                               0x00004400L // Already defined in milmod, milpat.h, ...
#define M_OFFSET                                   2L
#define M_ANGLE                                    0x00000800L // Already defined in milmod, milpat.h, ...
#define M_TRAINED_BOX_WIDTH                        48L
#define M_TRAINED_BOX_HEIGHT                       49L
#define M_WIDTH_MIN_INDEX                          10L         // 
#define M_WIDTH_MAX_INDEX                          20L         // 
#define M_STATUS_GAP_TOLERANCE                     22L
#define M_STATUS_GAP_MAX                           23L
#define M_STATUS_SCORE                             24L
#define M_TRAINED_INDEX                            25L
#define M_STATUS_SEARCH                            26L           
#define M_STATUS_OFFSET                            27L
#define M_STATUS_WIDTH_MIN                         28L
#define M_STATUS_WIDTH_MAX                         29L
#define M_WIDTH_VALUE                              31L
#define M_STATUS_FOUND                             32L
#define M_SCORE                                    0x00001400L // Already defined in milmod, milpat.h, ...
#define M_STATUS_INTENSITY_MIN                     50L
#define M_STATUS_INTENSITY_MAX                     51L
#define M_INTENSITY                                52L
#define M_TRAINING_WIDTH_NOMINAL                   60L
#define M_TRAINING_WIDTH_SCALE_MIN                 61L
#define M_TRAINING_WIDTH_SCALE_MAX                 62L
#define M_CLOSURE                                  77L // Also defined in miledge.h
#define M_INTENSITY_NOMINAL_MODE                   80L
#define M_INTENSITY_NOMINAL                        81L
#define M_INTENSITY_DELTA_POS                      82L
#define M_INTENSITY_DELTA_NEG                      83L
#define M_INTENSITY_MIN                            84L
#define M_INTENSITY_MAX                            85L
#define M_INTENSITY_MIN_INDEX                      86L
#define M_INTENSITY_MAX_INDEX                      87L
#define M_OFFSET_MAX_INDEX                         89L
#define M_NUMBER_FOUND                             90L

#define M_START_POS_X                              2820   // Already defined in milmod.h
#define M_START_POS_Y                              2821   // Already defined in milmod.h
#define M_END_POS_X                                2822   // Already defined in milmod.h
#define M_END_POS_Y                                2823   // Already defined in milmod.h

// General values
#define M_BEGIN                                    -1L
#define M_END                                      -2L
#define M_INFINITE                                 -1L // Also defined in Mil.h

// Result values
#define M_PASS                                     0x0002L     // Already defined in milim.h, ...
#define M_FAIL                                     4L          // Already defined in milmetrol.h, ...
#define M_FAIL_WIDTH_MIN                           7L          // 
#define M_FAIL_WIDTH_MAX                           8L          // 
#define M_FAIL_GAP_MAX                             9L          // 
#define M_FAIL_OFFSET                              10L         //
#define M_FAIL_NOT_FOUND                           11L         //
#define M_FAIL_INTENSITY_MIN                       12L         //
#define M_FAIL_INTENSITY_MAX                       13L         //

// Draw operation flags
#define M_DRAW_POSITION                            0x00000040L // Already defined in milmod.h, milpat.h, ...
#define M_DRAW_POSITION_POLYLINE                   2L          //
#define M_DRAW_INDEX                               0x00000100L // Already defines in miledge.h
#define M_DRAW_SEARCH_BOX                          6L          //    
#define M_DRAW_WIDTH                               0x00000008L // Already 
#define M_DRAW_LABEL                               0x00000001L // Already defines in miledge.h, milmetrol.h, ...
#define M_DRAW_TRAINING_IMAGE                      15L
#define M_DRAW_POSITION_INDEX                      20L

// Draw option flags
#define M_USER                                     0x00000001L // Already defines in mil.h,...
#define M_TRAINED                                  12L
#define M_TRAINED_PASS                             11L
#define M_TRAINED_FAIL                             9L
#define M_ALL                                      0x40000000L // Already defines in milmetrol.h,...
#define M_PASS                                     0x0002L     // Already defines in milmetrol.h,...
#define M_FAIL                                     4L          // Already defines in milmetrol.h,...
#define M_FAIL_WIDTH_MAX                           8L 
#define M_FAIL_WIDTH_MIN                           7L 
#define M_FAIL_OFFSET                              10L 

/***************************************************************************/
/* MbeadSave()/MbeadRestore()/MbeadStream()                                   */
/***************************************************************************/
#define M_MEMORY           (M_APP_INQUIRE_SYS_START+120L) /*5120*/  // Already defined in Mil.h
#define M_INTERACTIVE                    M_NULL // Already defined in    mil.h, milcal.h, milcode.h, milmeas.h, milocr.h, milpat.h, milmod.h

#define M_SAVE                             0x100L

#define M_RESTORE                           0x10L

#define M_LOAD                                 1L
#define M_INQUIRE_SIZE_BYTE                    2L

#define M_WITH_CALIBRATION            0x00020000L // Already in mil.h



/***************************************************************************/
/* Utilities                                                               */
/***************************************************************************/

#define M_TEMPLATE_LABEL_TAG                 0x01000000L   // =utilities=                 
#define M_TEMPLATE_INDEX_TAG                 0x02000000L   // =utilities=

#define M_TEMPLATE_LABEL(i)                  (M_TEMPLATE_LABEL_TAG   | (i))
#define M_TEMPLATE_INDEX(i)                  (M_TEMPLATE_INDEX_TAG   | (i))

   //*****************************************************************************************
   // CAPI function prototypes

#if M_MIL_USE_64BIT
   // Prototypes for 64 bits OS
   void MFTYPE MbeadControlInt64(MIL_ID     ContextBeadId,
                                 MIL_INT    LabelOrIndex,
                                 MIL_INT64  ControlType,
                                 MIL_INT64  ControlValue);

   void MFTYPE MbeadControlDouble(MIL_ID     ContextBeadId,
                                  MIL_INT    LabelOrIndex,
                                  MIL_INT64  ControlType,
                                  MIL_DOUBLE ControlValue);
#else

   // Prototypes for 32 bits OS
#define MbeadControlInt64  MbeadControl
#define MbeadControlDouble MbeadControl

   void MFTYPE MbeadControl(MIL_ID     ContextBeadId,
                            MIL_INT    LabelOrIndex,
                            MIL_INT64  ControlType,
                            MIL_DOUBLE ControlValue);
#endif

   MIL_ID   MFTYPE  MbeadAlloc(MIL_ID     SysId,
                               MIL_INT64  Strategy,
                               MIL_INT64  ControlFlag,
                               MIL_ID*    ContextBeadIdPtr);

   MIL_ID   MFTYPE  MbeadAllocResult(MIL_ID     SysId,
                                     MIL_INT64  ControlFlag,
                                     MIL_ID*    ResultBeadIdPtr);

   void     MFTYPE  MbeadFree(MIL_ID   ContextOrResultBeadId);


   MIL_INT  MFTYPE  MbeadInquire(MIL_ID     ContextOrResultBeadId,
                                 MIL_INT    LabelOrIndex,
                                 MIL_INT64  InquireType,
                                 void*      UserVarPtr);

   void     MFTYPE  MbeadTemplate(MIL_ID            ContextBeadId,
                                  MIL_INT64         Operation,
                                  MIL_INT64         BeadType,
                                  MIL_INT           LabelOrIndex,
                                  MIL_INT           GraListIdOrSizeOfArray,
                                  const MIL_DOUBLE* FirstArrayPtr,
                                  const MIL_DOUBLE* SecondArrayPtr,
                                  const MIL_INT*    ThirdArrayPtr,
                                  MIL_INT64         ControlFlag);

   void     MFTYPE  MbeadTrain(MIL_ID     ContextBeadId,
                               MIL_ID     TrainingImageBufId,
                               MIL_INT64  ControlFlag);

   void     MFTYPE  MbeadVerify(MIL_ID     ContextBeadId,
                                MIL_ID     TargetImageBufId,
                                MIL_ID     ResultBeadId,
                                MIL_INT64  ControlFlag);

   void     MFTYPE  MbeadGetResult(MIL_ID       ResultBeadId,
                                   MIL_INT      LabelOrIndex,
                                   MIL_INT      ResultIndex,
                                   MIL_INT64    ResultType,
                                   void*        UserVarPtr);

   void     MFTYPE   MbeadGetNeighbors(MIL_ID     ContextBeadId,
                                       MIL_INT    LabelOrIndex,
                                       MIL_DOUBLE PositionX,
                                       MIL_DOUBLE PositionY,
                                       MIL_INT*   TemplateLabelPtr,
                                       MIL_INT*   PointIndexPtr,
                                       MIL_INT64  ControlFlag);

   void     MFTYPE  MbeadDraw(MIL_ID      ContextGraId,
                              MIL_ID      ContextOrResultBeadId,
                              MIL_ID      DstImageBufOrListGraId,
                              MIL_INT64   DrawOperation,
                              MIL_INT64   DrawOption,
                              MIL_INT     LabelOrIndex,
                              MIL_INT     Index,
                              MIL_INT64   ControlFlag);

#if M_MIL_USE_UNICODE

   MIL_ID MFTYPE MbeadRestoreW(MIL_CONST_TEXTW_PTR FileName,
                               MIL_ID     SysId,
                               MIL_INT64  ControlFlag,
                               MIL_ID*    ContextBeadIdPtr);

   void MFTYPE MbeadSaveW(MIL_CONST_TEXTW_PTR FileName,
                          MIL_ID     ContextBeadId,
                          MIL_INT64  ControlFlag);

   void MFTYPE MbeadStreamW(MIL_TEXTW_PTR MemPtrOrFileName,
                            MIL_ID     SysId,
                            MIL_INT64  Operation,
                            MIL_INT64  StreamType,
                            MIL_DOUBLE Version,
                            MIL_INT64  ControlFlag,
                            MIL_ID*    ContextBeadIdPtr,
                            MIL_INT*   SizeByteVarPtr);

   MIL_ID MFTYPE MbeadRestoreA(MIL_CONST_TEXTA_PTR FileName,
                               MIL_ID      SysId,
                               MIL_INT64   ControlFlag,
                               MIL_ID*     ContextBeadIdPtr);

   void MFTYPE MbeadSaveA(MIL_CONST_TEXTA_PTR FileName,
                          MIL_ID      ContextBeadId,
                          MIL_INT64   ControlFlag);

   void MFTYPE MbeadStreamA(MIL_TEXTA_PTR      MemPtrOrFileName,
                            MIL_ID     SysId,
                            MIL_INT64  Operation,
                            MIL_INT64  StreamType,
                            MIL_DOUBLE Version,
                            MIL_INT64  ControlFlag,
                            MIL_ID*    ContextBeadIdPtr,
                            MIL_INT*   SizeByteVarPtr);

#if M_MIL_UNICODE_API
#define MbeadSave           MbeadSaveW
#define MbeadRestore        MbeadRestoreW
#define MbeadStream         MbeadStreamW
#else
#define MbeadSave           MbeadSaveA
#define MbeadRestore        MbeadRestoreA
#define MbeadStream         MbeadStreamA
#endif

#else

   MIL_ID MFTYPE MbeadRestore(MIL_CONST_TEXT_PTR FileName,
                              MIL_ID             SysId,
                              MIL_INT64          ControlFlag,
                              MIL_ID*            ContextBeadIdPtr);

   void MFTYPE MbeadSave(MIL_CONST_TEXT_PTR FileName,
                         MIL_ID             ContextBeadId,
                         MIL_INT64          ControlFlag);

   void MFTYPE MbeadStream(MIL_TEXT_PTR MemPtrOrFileName,
                           MIL_ID       SysId,
                           MIL_INT64    Operation,
                           MIL_INT64    StreamType,
                           MIL_DOUBLE   Version,
                           MIL_INT64    ControlFlag,
                           MIL_ID*      ContextBeadIdPtr,
                           MIL_INT*     SizeByteVarPtr);
#endif

   //*****************************************************************************************
#ifdef __cplusplus
}
#endif

#ifdef __cplusplus

inline void MFTYPE MbeadStreamCpp(MilStreamParam MemPtrOrFileName,
                                  MIL_ID         SysId,
                                  MIL_INT64      Operation,
                                  MIL_INT64      StreamType,
                                  MIL_DOUBLE     Version,
                                  MIL_INT64      ControlFlag,
                                  MIL_ID*        ContextBeadIdPtr,
                                  MIL_INT*       SizeByteVarPtr)
   {
   MbeadStream(MemPtrOrFileName.m_Param, SysId, Operation, StreamType, Version, ControlFlag, ContextBeadIdPtr, SizeByteVarPtr);
   }

#undef  MbeadStream
#define MbeadStream MbeadStreamCpp

#endif // __cplusplus

#if M_MIL_USE_64BIT
#ifdef __cplusplus
//////////////////////////////////////////////////////////////
// M3dmapControl function definition when compiling c++ files
//////////////////////////////////////////////////////////////
#if !M_MIL_USE_LINUX
inline void MbeadControl(MIL_ID ContextBeadId, MIL_INT LabelOrIndex, MIL_INT64  ControlType, int ControlValue)
   {
   MbeadControlInt64(ContextBeadId, LabelOrIndex, ControlType, ControlValue);
   };
#endif
inline void MbeadControl(MIL_ID ContextBeadId, MIL_INT LabelOrIndex, MIL_INT64  ControlType, MIL_INT32 ControlValue)
   {
   MbeadControlInt64(ContextBeadId, LabelOrIndex, ControlType, ControlValue);
   }

inline void MbeadControl(MIL_ID ContextBeadId, MIL_INT LabelOrIndex, MIL_INT64  ControlType, MIL_INT64 ControlValue)
   {
   MbeadControlInt64(ContextBeadId, LabelOrIndex, ControlType, ControlValue);
   }

inline void MbeadControl(MIL_ID ContextBeadId, MIL_INT LabelOrIndex, MIL_INT64  ControlType, MIL_DOUBLE ControlValue)
   {
   MbeadControlDouble(ContextBeadId, LabelOrIndex, ControlType, ControlValue);
   }
#else
//////////////////////////////////////////////////////////////
// For C file, call the default function, i.e. Double one
//////////////////////////////////////////////////////////////
#define MbeadControl  MbeadControlDouble

#endif // __cplusplus
#endif // M_MIL_USE_64BIT

#if M_MIL_USE_SAFE_TYPE

//////////////////////////////////////////////////////////////
// See milos.h for explanation about these functions.
//////////////////////////////////////////////////////////////
// -------------------------------------------------------------------------
// MbeadGetResult
inline void MFTYPE MbeadGetResultSafeType(MIL_ID ResultBeadId, MIL_INT LabelOrIndex, MIL_INT ResultIndex, MIL_INT64 ResultType, MilVoidPtr ResultArrayPtr)
   {
   MIL_INT64 RequiredParamType = M_PARAM_TYPE_MIL_INT64;
   if(!(M_DEFAULT_DATA_TYPE_BIT_SET(ResultType) || M_RECOMMENDED_DATA_TYPE_BIT_SET(ResultType)))
      {
      MbeadGetResult(ResultBeadId, LabelOrIndex, ResultIndex, ResultType | M_DEFAULT_DATA_TYPE, &RequiredParamType);
      }
   if(!MfuncPointerIsCompatible(RequiredParamType, ResultArrayPtr.Type, ResultType))
      {
      SafeTypeError(MIL_TEXT("MbeadGetResult"));
      }
   MbeadGetResult(ResultBeadId, LabelOrIndex, ResultIndex, ResultType, ResultArrayPtr.Ptr);
   }

inline void MFTYPE MbeadGetResultUnsafe(MIL_ID ResultBeadId, MIL_INT LabelOrIndex, MIL_INT ResultIndex, MIL_INT64 ResultType, void *ResultArrayPtr)
   {
   MbeadGetResult(ResultBeadId, LabelOrIndex, ResultIndex, ResultType, ResultArrayPtr);
   }

// ----------------------------------------------------------
// MbeadInquire
inline MIL_INT MFTYPE MbeadInquireSafeType(MIL_ID ContextOrResultBeadId, MIL_INT LabelOrIndex, MIL_INT64 InquireType, MilVoidPtr UserVarPtr)
   {
   MIL_INT64 RequiredParamType = M_PARAM_TYPE_MIL_INT64;
   if(!(M_DEFAULT_DATA_TYPE_BIT_SET(InquireType) || M_RECOMMENDED_DATA_TYPE_BIT_SET(InquireType)))
      {
      MbeadInquire(ContextOrResultBeadId, LabelOrIndex, InquireType | M_DEFAULT_DATA_TYPE, &RequiredParamType);
      }
   if(!MfuncPointerIsCompatible(RequiredParamType, UserVarPtr.Type, InquireType))
      {
      SafeTypeError(MIL_TEXT("MbeadInquire"));
      }
   return MbeadInquire(ContextOrResultBeadId, LabelOrIndex, InquireType, UserVarPtr.Ptr);
   }

inline MIL_INT MFTYPE MbeadInquireUnsafe(MIL_ID ContextOrResultBeadId, MIL_INT LabelOrIndex, MIL_INT64 InquireType, void *UserVarPtr)
   {
   return MbeadInquire(ContextOrResultBeadId, LabelOrIndex, InquireType, UserVarPtr);
   }

#define MbeadGetResult        MbeadGetResultSafeType
#define MbeadInquire          MbeadInquireSafeType

#else // #if M_MIL_USE_SAFE_TYPE

#define MbeadGetResultUnsafe        MbeadGetResult
#define MbeadInquireUnsafe          MbeadInquire

#endif // #if M_MIL_USE_SAFE_TYPE

// ----------------------------------------------------------
// Overload for std::vector.
#if defined(M_MIL_USE_VECTOR) && M_MIL_USE_VECTOR
template <typename UserType>
inline MIL_INT MFTYPE MbeadInquire(MIL_ID ContextOrResultBeadId, MIL_INT LabelOrIndex, MIL_INT64  InquireType, std::vector<UserType> &UserVarPtr)
   {
   // If the given MIL data type is not the same as the SrcType, change it to the correct one
   // and give a warning.
   MIL_INT64 InternalTrueDataTypeForStdVector = MilTraits<UserType>::TypeFlag;

#if M_MIL_USE_SAFE_TYPE
   if(M_GET_HLVLDATATYPE(InquireType) != 0)
      {
      SafeTypeError(MIL_TEXT("MbeadInquire"), MIL_TEXT("Combination value for the required data type is not supported with std::vector overload."));
      }
#endif

   InquireType = M_STRIP_HLVLDATATYPE(InquireType) + InternalTrueDataTypeForStdVector;

   MIL_INT InternalNumberOfElementsForStdVector = 0;
   MbeadInquire(ContextOrResultBeadId, LabelOrIndex, M_STRIP_HLVLDATATYPE(InquireType) + M_NB_ELEMENTS + M_TYPE_MIL_INT, &InternalNumberOfElementsForStdVector);

   UserVarPtr.resize(InternalNumberOfElementsForStdVector);

   if(InternalNumberOfElementsForStdVector > 0)
      {
      return MbeadInquire(ContextOrResultBeadId, LabelOrIndex, InquireType, &UserVarPtr[0]);
      }
   return 0;
   }
template <typename UserType>
inline void MFTYPE MbeadGetResult(MIL_ID ResultBeadId, MIL_INT LabelOrIndex, MIL_INT ResultIndex, MIL_INT64  ResultType, std::vector<UserType> &ResultArrayPtr)
   {
   //! If the given MIL data type is not the same as the SrcType, change it to the correct one
   //! and give a warning.
   MIL_INT64 InternalTrueDataTypeForStdVector = MilTraits<UserType>::TypeFlag;

#if M_MIL_USE_SAFE_TYPE
   if(M_GET_HLVLDATATYPE(ResultType) != 0)
      {
      SafeTypeError(MIL_TEXT("MbeadGetResult"), MIL_TEXT("Combination value for the required data type is not supported with std::vector overload."));
      }
#endif

   ResultType = M_STRIP_HLVLDATATYPE(ResultType) + InternalTrueDataTypeForStdVector;

   MIL_INT InternalNumberOfElementsForStdVector = 0;
   MbeadGetResult(ResultBeadId, LabelOrIndex, ResultIndex, M_STRIP_HLVLDATATYPE(ResultType) + M_NB_ELEMENTS + M_TYPE_MIL_INT, &InternalNumberOfElementsForStdVector);

   ResultArrayPtr.resize(InternalNumberOfElementsForStdVector);

   if(InternalNumberOfElementsForStdVector > 0)
      {
      MbeadGetResult(ResultBeadId, LabelOrIndex, ResultIndex, ResultType, &ResultArrayPtr[0]);
      }
   }

// ----------------------------------------------------------
// Overloads for std::vector in MbeadTemplate.
inline void MFTYPE MbeadTemplate(MIL_ID                        ContextBeadId,
                                 MIL_INT64                     Operation,
                                 MIL_INT64                     BeadType,
                                 MIL_INT                       LabelOrIndex,
                                 MIL_INT                       GraListIdOrSizeOfArray,
                                 CMilArrayParamIn              FirstArrayPtr,
                                 CMilArrayParamIn              SecondArrayPtr,
                                 CMilArrayParamIn              ThirdArrayPtr,
                                 MIL_INT64                     ControlFlag)
   {
#if M_MIL_USE_SAFE_TYPE
   if(!FirstArrayPtr.IsValidParam() || !SecondArrayPtr.IsValidParam() || !ThirdArrayPtr.IsValidParam())
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("FirstArrayPtr, SecondArrayPtr or ThirdArrayPtr cannot be an non zero integer."));
      }
   if(GraListIdOrSizeOfArray <= 0)
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("GraListIdOrSizeOfArray parameter must be greater than zero."));
      }
   if(!FirstArrayPtr.IsNullPtr() && FirstArrayPtr.GetMilDataType() != MilTraits<MIL_DOUBLE>::TypeFlag)
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("The data type of FirstArrayPtr must be MIL_DOUBLE."));
      }
   if(!SecondArrayPtr.IsNullPtr() && SecondArrayPtr.GetMilDataType() != MilTraits<MIL_DOUBLE>::TypeFlag)
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("The data type of SecondArrayPtr must be MIL_DOUBLE."));
      }
   if(!ThirdArrayPtr.IsNullPtr() && ThirdArrayPtr.GetMilDataType() != MilTraits<MIL_INT>::TypeFlag)
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("The data type of ThirdArrayPtr must be MIL_INT."));
      }
   if((FirstArrayPtr.Size<MIL_DOUBLE>() != SecondArrayPtr.Size<MIL_DOUBLE>() && !FirstArrayPtr.IsNullPtr()  && !SecondArrayPtr.IsNullPtr()) ||
      (FirstArrayPtr.Size<MIL_DOUBLE>() != ThirdArrayPtr.Size<MIL_INT>()     && !FirstArrayPtr.IsNullPtr()  && !ThirdArrayPtr.IsNullPtr()) ||
      (SecondArrayPtr.Size<MIL_DOUBLE>() != ThirdArrayPtr.Size<MIL_INT>()    && !SecondArrayPtr.IsNullPtr() && !ThirdArrayPtr.IsNullPtr()))
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("The input vectors must have the same size!"));
      }
   if(FirstArrayPtr.IsEmpty<MIL_DOUBLE>() || SecondArrayPtr.IsEmpty<MIL_DOUBLE>() || ThirdArrayPtr.IsEmpty<MIL_INT>())
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("The input vectors cannot be empty."));
      }
#endif

   MIL_INT GraListIdOrSizeOfArrayMax = !FirstArrayPtr.IsNullPtr() ? FirstArrayPtr.Size<MIL_DOUBLE>() :
      !SecondArrayPtr.IsNullPtr() ? SecondArrayPtr.Size<MIL_DOUBLE>() :
      !ThirdArrayPtr.IsNullPtr() ? ThirdArrayPtr.Size<MIL_INT>() : M_NULL;

   if(GraListIdOrSizeOfArray == M_DEFAULT || GraListIdOrSizeOfArray > GraListIdOrSizeOfArrayMax)
      {
#if M_MIL_USE_SAFE_TYPE
      if(GraListIdOrSizeOfArray > GraListIdOrSizeOfArrayMax && GraListIdOrSizeOfArray != M_DEFAULT)
         {
         SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("GraListIdOrSizeOfArray parameter must be smaller or equal (M_DEFAULT) to the size of input vectors."));
         }
#endif
      GraListIdOrSizeOfArray = GraListIdOrSizeOfArrayMax;
      }

   MbeadTemplate(ContextBeadId,
                 Operation,
                 BeadType,
                 LabelOrIndex,
                 GraListIdOrSizeOfArray,
                 FirstArrayPtr.GetData<MIL_DOUBLE>(),
                 SecondArrayPtr.GetData<MIL_DOUBLE>(),
                 ThirdArrayPtr.GetData<MIL_INT>(),
                 ControlFlag);
   }
inline void MFTYPE MbeadTemplate(MIL_ID                        ContextBeadId,
                                 MIL_INT64                     Operation,
                                 MIL_INT64                     BeadType,
                                 MIL_INT                       LabelOrIndex,
                                 MIL_INT                       GraListIdOrSizeOfArray,
                                 CMilArrayParamIn              FirstArrayPtr,
                                 CMilArrayParamIn              SecondArrayPtr,
                                 const MIL_INT*                ThirdArrayPtr,
                                 MIL_INT64                     ControlFlag)
   {
#if M_MIL_USE_SAFE_TYPE
   if(!FirstArrayPtr.IsValidParam() || !SecondArrayPtr.IsValidParam())
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("FirstArrayPtr or SecondArrayPtr cannot be an non zero integer."));
      }
   if(GraListIdOrSizeOfArray <= 0)
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("GraListIdOrSizeOfArray parameter must be greater than zero."));
      }
   if(!FirstArrayPtr.IsNullPtr() && FirstArrayPtr.GetMilDataType() != MilTraits<MIL_DOUBLE>::TypeFlag)
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("The data type of FirstArrayPtr must be MIL_DOUBLE."));
      }
   if(!SecondArrayPtr.IsNullPtr() && SecondArrayPtr.GetMilDataType() != MilTraits<MIL_DOUBLE>::TypeFlag)
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("The data type of SecondArrayPtr must be MIL_DOUBLE."));
      }
   if(FirstArrayPtr.Size<MIL_DOUBLE>() != SecondArrayPtr.Size<MIL_DOUBLE>() && !FirstArrayPtr.IsNullPtr() && !SecondArrayPtr.IsNullPtr())
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("The input vectors must have the same size!"));
      }
   if(FirstArrayPtr.IsEmpty<MIL_DOUBLE>() || SecondArrayPtr.IsEmpty<MIL_DOUBLE>())
      {
      SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("The input vectors cannot be empty."));
      }
#endif

   MIL_INT GraListIdOrSizeOfArrayMax = !FirstArrayPtr.IsNullPtr() ? FirstArrayPtr.Size<MIL_DOUBLE>() :
      !SecondArrayPtr.IsNullPtr() ? SecondArrayPtr.Size<MIL_DOUBLE>() : M_NULL;

   if(GraListIdOrSizeOfArray == M_DEFAULT || GraListIdOrSizeOfArray > GraListIdOrSizeOfArrayMax)
      {
#if M_MIL_USE_SAFE_TYPE
      if(GraListIdOrSizeOfArray > GraListIdOrSizeOfArrayMax && GraListIdOrSizeOfArray != M_DEFAULT)
         {
         SafeTypeError(MIL_TEXT("MbeadTemplate"), MIL_TEXT("GraListIdOrSizeOfArray parameter must be smaller or equal (M_DEFAULT) to the size of input vectors."));
         }
#endif
      GraListIdOrSizeOfArray = GraListIdOrSizeOfArrayMax;
      }

   MbeadTemplate(ContextBeadId,
                 Operation,
                 BeadType,
                 LabelOrIndex,
                 GraListIdOrSizeOfArray,
                 FirstArrayPtr.GetData<MIL_DOUBLE>(),
                 SecondArrayPtr.GetData<MIL_DOUBLE>(),
                 ThirdArrayPtr,
                 ControlFlag);
   }

// ----------------------------------------------------------
// Overloads for std::vector in MxxxStream.
inline void MFTYPE MbeadStream(std::vector<MIL_UINT8>  &MemPtrOrFileName,
                                MIL_ID                 SysId,
                                MIL_INT64              Operation,
                                MIL_INT64              StreamType,
                                MIL_DOUBLE             Version,
                                MIL_INT64              ControlFlag,
                                MIL_ID*                McontextIdPtr,
                                MIL_INT*               SizeByteVarPtr)
   {
   MxxxStreamForStdVector(MemPtrOrFileName,
                          SysId,
                          Operation,
                          StreamType,
                          Version,
                          ControlFlag,
                          McontextIdPtr,
                          SizeByteVarPtr,
                          MbeadStream);
   }
#endif // defined(M_MIL_USE_VECTOR) && M_MIL_USE_VECTOR

#if M_MIL_USE_STRING
/***************************************************************************/
/* BEAD MODULE                                                             */
/***************************************************************************/

#if M_MIL_USE_UNICODE
#if M_MIL_UNICODE_API

inline void MFTYPE MbeadSaveW(const MIL_STRING& FileName, MIL_ID ContextBeadId, MIL_INT64 ControlFlag)
   {
   return MbeadSaveW(FileName.c_str(), ContextBeadId, ControlFlag);
   }

inline MIL_ID MFTYPE MbeadRestoreW(const MIL_STRING& sFileName, MIL_ID SysId, MIL_INT64 ControlFlag, MIL_ID* ContextBeadIdPtr)
   {
   return MbeadRestoreW(sFileName.c_str(), SysId, ControlFlag, ContextBeadIdPtr);
   }

#else
inline void MFTYPE MbeadSaveA(const MIL_STRING& FileName, MIL_ID ContextBeadId, MIL_INT64 ControlFlag)
   {
   return MbeadSaveA(FileName.c_str(), ContextBeadId, ControlFlag);
   }

inline MIL_ID MFTYPE MbeadRestoreA(const MIL_STRING& sFileName, MIL_ID SysId, MIL_INT64 ControlFlag, MIL_ID* ContextBeadIdPtr)
   {
   return MbeadRestoreA(sFileName.c_str(), SysId, ControlFlag, ContextBeadIdPtr);
   }

#endif /* M_MIL_UNICODE_API */
#else
inline void MFTYPE MbeadSave(const MIL_STRING& FileName, MIL_ID ContextBeadId, MIL_INT64 ControlFlag)
   {
   return MbeadSave(FileName.c_str(), ContextBeadId, ControlFlag);
   }

inline MIL_ID MFTYPE MbeadRestore(const MIL_STRING& sFileName, MIL_ID SysId, MIL_INT64 ControlFlag, MIL_ID* ContextBeadIdPtr)
   {
   return MbeadRestore(sFileName.c_str(), SysId, ControlFlag, ContextBeadIdPtr);
   }

#endif /* M_MIL_USE_UNICODE */
#endif /* M_MIL_USE_STRING*/

////////////////////////////////////////////////////////////////////////////////
// MIL_UNIQUE_ID support

#if M_MIL_USE_MIL_UNIQUE_ID

#if M_MIL_USE_SAFE_TYPE
template <> inline bool MilIsCorrectObjectType<&MbeadFree>(MIL_INT64 ObjectType)
   {
   return (ObjectType & ~M_USER_DEFINE_LOW_ATTRIBUTE) == M_BEAD_OBJECT;
   }
#endif

typedef MIL_UNIQUE_ID<&MbeadFree> MIL_UNIQUE_BEAD_ID;

#if M_MIL_USE_MOVE_SEMANTICS

inline MIL_UNIQUE_BEAD_ID MbeadAlloc(MIL_ID SysId, MIL_INT64 Strategy, MIL_INT64 ControlFlag, MIL_UNIQUE_ID_TAG)
   {
   return MIL_UNIQUE_BEAD_ID(MbeadAlloc(SysId, Strategy, ControlFlag, M_NULL));
   }
inline MIL_UNIQUE_BEAD_ID MbeadAllocResult(MIL_ID SysId, MIL_INT64 ControlFlag, MIL_UNIQUE_ID_TAG)
   {
   return MIL_UNIQUE_BEAD_ID(MbeadAllocResult(SysId, ControlFlag, M_NULL));
   }
inline MIL_UNIQUE_BEAD_ID MbeadRestore(MIL_CONST_TEXT_PTR FileName, MIL_ID SysId, MIL_INT64 ControlFlag, MIL_UNIQUE_ID_TAG)
   {
   return MIL_UNIQUE_BEAD_ID(MbeadRestore(FileName, SysId, ControlFlag, M_NULL));
   }
#if M_MIL_USE_STRING
inline MIL_UNIQUE_BEAD_ID MbeadRestore(const MIL_STRING& FileName, MIL_ID SysId, MIL_INT64 ControlFlag, MIL_UNIQUE_ID_TAG)
   {
   return MIL_UNIQUE_BEAD_ID(MbeadRestore(FileName, SysId, ControlFlag, M_NULL));
   }
#endif // M_MIL_USE_STRING
template <MilFreeFuncType FreeFunc> inline void MbeadFree(const MIL_UNIQUE_ID<FreeFunc>&) = delete;

inline void MbeadStream(MilStreamParam       MemPtrOrFileName,
                        MIL_ID               SysId           ,
                        MIL_INT64            Operation       ,
                        MIL_INT64            StreamType      ,
                        MIL_DOUBLE           Version         ,
                        MIL_INT64            ControlFlag     ,
                        MIL_UNIQUE_BEAD_ID*  ContextBeadIdPtr,
                        MIL_INT*             SizeByteVarPtr  )
   {
   MxxxStreamForMilUniqueId(MemPtrOrFileName, SysId, Operation, StreamType, Version, ControlFlag, ContextBeadIdPtr, SizeByteVarPtr, MbeadStream);
   }

#endif // M_MIL_USE_MOVE_SEMANTICS
#endif // M_MIL_USE_MIL_UNIQUE_ID

// End of MIL_UNIQUE_ID support
////////////////////////////////////////////////////////////////////////////////

#endif // !M_MIL_LITE
#endif // __MIL_BEAD_H__
