#include "common.h"
void PrintHeader()
{
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n")
MIL_TEXT("CalGenChessGrid\n\n")
MIL_TEXT("[SYNOPSIS]\n")
MIL_TEXT("This example demonstrates how to generate an image of a\n")
MIL_TEXT("calibration grid according to the user-defined specifications in\n")
MIL_TEXT("gridconfig.h. It can generate chessboard grids with or without\n")
MIL_TEXT("fiducials. The resulting grid can be used with the MIL camera\n")
MIL_TEXT("calibration module (Mcal).\n\n")
MIL_TEXT("[MODULES USED]\n")
MIL_TEXT("Modules used: application, buffer, code, display, graphics, image\n")
MIL_TEXT("processing, system.\n\n")
MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
}
inline void DrawThickRect(MIL_ID ContextGraId, MIL_ID ImageId, MIL_DOUBLE Color,
MIL_INT ThicknessX, MIL_INT ThicknessY,
MIL_INT StartX, MIL_INT StartY,
MIL_INT EndX, MIL_INT EndY)
{
MgraColor(ContextGraId, Color);
MgraRectFill(ContextGraId, ImageId, StartX , StartY , EndX , StartY+ThicknessY-1);
MgraRectFill(ContextGraId, ImageId, StartX , EndY-ThicknessY+1, EndX , EndY );
MgraRectFill(ContextGraId, ImageId, StartX , StartY , StartX+ThicknessX-1, EndY );
MgraRectFill(ContextGraId, ImageId, EndX-ThicknessX+1, StartY , EndX , EndY );
}
struct AnnotationStruct
{
MIL_DOUBLE PixelsPerSquareX;
MIL_DOUBLE PixelsPerSquareY;
MIL_INT MaxPixelsPerSquareInt;
MIL_INT ImageSizeX;
MIL_INT ImageSizeY;
MIL_INT FullSizeX;
MIL_INT FullSizeY;
MIL_INT LeftBorder;
MIL_INT RightBorder;
MIL_INT TopBorder;
MIL_INT BottomBorder;
MIL_INT BorderThickness;
MIL_INT LastPixelOfGridX;
MIL_INT LastPixelOfGridY;
};
AnnotationStruct ComputeAnnotationParameters(const GridInfoStruct& GridInfo)
{
AnnotationStruct Annotation;
if (DPI <= 0.0)
throw MIL_TEXT("DPI must be positive");
MIL_DOUBLE PixelsPerInch = DPI;
MIL_DOUBLE PixelsPerWorldUnit = GetInchesPerWorldUnit(UNIT) * PixelsPerInch;
Annotation.PixelsPerSquareX = GridInfo.SpacingX * PixelsPerWorldUnit;
Annotation.PixelsPerSquareY = GridInfo.SpacingY * PixelsPerWorldUnit;
Annotation.MaxPixelsPerSquareInt = static_cast<MIL_INT>(ceil(
Annotation.PixelsPerSquareX > Annotation.PixelsPerSquareY ?
Annotation.PixelsPerSquareX : Annotation.PixelsPerSquareY));
Annotation.ImageSizeX = static_cast<MIL_INT>(ceil(GridInfo.NumSquaresX * Annotation.PixelsPerSquareX));
Annotation.ImageSizeY = static_cast<MIL_INT>(ceil(GridInfo.NumSquaresY * Annotation.PixelsPerSquareY));
if (DRAW_ANNOTATIONS)
{
Annotation.BorderThickness = static_cast<MIL_INT>(ceil(BORDER_THICKNESS * Annotation.MaxPixelsPerSquareInt));
Annotation.LeftBorder = Annotation.MaxPixelsPerSquareInt;
Annotation.RightBorder = Annotation.MaxPixelsPerSquareInt;
Annotation.TopBorder = Annotation.MaxPixelsPerSquareInt;
Annotation.BottomBorder = static_cast<MIL_INT>(Annotation.ImageSizeX * BOTTOM_SPACE_FACTOR);
}
else
{
Annotation.BorderThickness = 0;
Annotation.LeftBorder = 0;
Annotation.RightBorder = 0;
Annotation.TopBorder = 0;
Annotation.BottomBorder = 0;
}
Annotation.FullSizeX = Annotation.ImageSizeX + Annotation.LeftBorder + Annotation.RightBorder;
Annotation.FullSizeY = Annotation.ImageSizeY + Annotation.TopBorder + Annotation.BottomBorder;
Annotation.LastPixelOfGridX = Annotation.LeftBorder + Annotation.ImageSizeX - 1;
Annotation.LastPixelOfGridY = Annotation.TopBorder + Annotation.ImageSizeY - 1;
return Annotation;
}
void DrawAnnotations(MIL_ID ContextGraId, MIL_ID FullImageId, const GridInfoStruct& GridInfo, const AnnotationStruct& Annotation)
{
DrawThickRect(ContextGraId, FullImageId, BORDER_COLOR,
Annotation.BorderThickness,
Annotation.BorderThickness,
Annotation.LeftBorder - Annotation.BorderThickness,
Annotation.TopBorder - Annotation.BorderThickness,
Annotation.LastPixelOfGridX + Annotation.BorderThickness,
Annotation.LastPixelOfGridY + Annotation.BorderThickness);
MIL_INT FontSize = static_cast<MIL_INT>(FONT_SIZE_FACTOR * Annotation.ImageSizeX);
if (FontSize <= 9)
throw MIL_TEXT("Font size is too small, use a higher DPI");
MgraFont(ContextGraId, MIL_FONT_NAME(FONT_NAME));
MgraControl(ContextGraId, M_FONT_SIZE, FontSize);
MgraColor(ContextGraId, FOREGROUND_COLOR);
MgraControl(ContextGraId, M_BACKCOLOR, BACKGROUND_COLOR);
const MIL_INT MAX_LEGEND_LENGTH = 256;
MIL_TEXT_CHAR Legend[MAX_LEGEND_LENGTH];
MIL_CONST_TEXT_PTR UnitName = GetUnitName(UNIT);
MosSprintf(Legend, MAX_LEGEND_LENGTH,
MIL_TEXT("Grid size: %g %s x %g %s%sRow/column number: %d x %d%sRow/column spacing: %g %s x %g %s"),
GridInfo.GridSizeX, UnitName, GridInfo.GridSizeY, UnitName, SEPARATOR,
(int)(GridInfo.NumSquaresY - 2 * NUM_SQUARES_FOR_QUIET_ZONE + 1),
(int)(GridInfo.NumSquaresX - 2 * NUM_SQUARES_FOR_QUIET_ZONE + 1), SEPARATOR,
GridInfo.SpacingY, UnitName, GridInfo.SpacingX, UnitName);
MIL_INT TextVerticalOffset = static_cast<MIL_INT>(TEXT_VERTICAL_OFFSET * Annotation.ImageSizeX);
MgraText(ContextGraId, FullImageId, Annotation.PixelsPerSquareX, Annotation.LastPixelOfGridY + TextVerticalOffset, Legend);
#if NUM_FIDUCIALS > 0
const MIL_INT TRIANGLE_LENGTH_TO_WIDTH_RATIO = 2;
MIL_INT RefPointSquareNoX = GridInfo.GetReferencePositionX();
MIL_INT RefPointSquareNoY = GridInfo.GetReferencePositionY();
MIL_INT RefPointPixelPosX = static_cast<MIL_INT>(RefPointSquareNoX * Annotation.PixelsPerSquareX) + Annotation.LeftBorder;
MIL_INT RefPointPixelPosY = static_cast<MIL_INT>(RefPointSquareNoY * Annotation.PixelsPerSquareY) + Annotation.TopBorder;
MIL_INT TriangleOffset = static_cast<MIL_INT>(ceil(TRIANGLE_OFFSET * Annotation.MaxPixelsPerSquareInt));
MIL_INT TriangleLength = static_cast<MIL_INT>(ceil(TRIANGLE_LENGTH * Annotation.MaxPixelsPerSquareInt));
MgraColor(ContextGraId, FOREGROUND_COLOR);
MIL_INT TriangleVerticesX[3], TriangleVerticesY[3];
TriangleVerticesX[0] = RefPointPixelPosX;
TriangleVerticesX[1] = TriangleVerticesX[0] - TriangleLength / (2 * TRIANGLE_LENGTH_TO_WIDTH_RATIO);
TriangleVerticesX[2] = TriangleVerticesX[0] + TriangleLength / (2 * TRIANGLE_LENGTH_TO_WIDTH_RATIO);
TriangleVerticesY[0] = Annotation.TopBorder - TriangleOffset;
TriangleVerticesY[1] = TriangleVerticesY[0] - TriangleLength;
TriangleVerticesY[2] = TriangleVerticesY[1];
MgraLines(ContextGraId, FullImageId, 3, TriangleVerticesX, TriangleVerticesY, M_NULL, M_NULL, M_POLYGON+M_FILLED);
if (RefPointSquareNoX <= GridInfo.NumSquaresX / 2)
{
TriangleVerticesX[0] = Annotation.LeftBorder - TriangleOffset;
TriangleVerticesX[1] = TriangleVerticesX[0] - TriangleLength;
}
else
{
TriangleVerticesX[0] = Annotation.LastPixelOfGridX + TriangleOffset;
TriangleVerticesX[1] = TriangleVerticesX[0] + TriangleLength;
}
TriangleVerticesX[2] = TriangleVerticesX[1];
TriangleVerticesY[0] = RefPointPixelPosY;
TriangleVerticesY[1] = TriangleVerticesY[0] - TriangleLength / (2 * TRIANGLE_LENGTH_TO_WIDTH_RATIO);
TriangleVerticesY[2] = TriangleVerticesY[0] + TriangleLength / (2 * TRIANGLE_LENGTH_TO_WIDTH_RATIO);
MgraLines(ContextGraId, FullImageId, 3, TriangleVerticesX, TriangleVerticesY, M_NULL, M_NULL, M_POLYGON+M_FILLED);
#endif
}
void SetZoomFactor(MIL_ID DispId, MIL_INT GridSizeX, MIL_INT GridSizeY)
{
MIL_DOUBLE ZoomFactor = 1.0;
if (GridSizeX > MAX_DISPLAY_SIZE_X)
ZoomFactor = static_cast<MIL_DOUBLE>(MAX_DISPLAY_SIZE_X) / GridSizeX;
if (GridSizeY > MAX_DISPLAY_SIZE_Y)
{
MIL_DOUBLE MaxZoomFactor = static_cast<MIL_DOUBLE>(MAX_DISPLAY_SIZE_Y) / GridSizeY;
if (MaxZoomFactor < ZoomFactor)
ZoomFactor = MaxZoomFactor;
}
if (ZoomFactor < 1.0)
MdispZoom(DispId, ZoomFactor, ZoomFactor);
}
struct MILObjectsStruture
{
MIL_ID AppId;
MIL_ID SysId;
MIL_ID ContextGraId;
MIL_ID FullImageId;
MIL_ID GridImageId;
MIL_ID DispId;
MILObjectsStruture()
: AppId (M_NULL),
SysId (M_NULL),
ContextGraId(M_NULL),
FullImageId (M_NULL),
GridImageId (M_NULL),
DispId (M_NULL)
{
}
~MILObjectsStruture()
{
if (DispId != M_NULL) MdispFree(DispId );
if (GridImageId != M_NULL) MbufFree(GridImageId );
if (FullImageId != M_NULL) MbufFree(FullImageId );
if (ContextGraId != M_NULL) MgraFree(ContextGraId);
if (SysId != M_NULL) MsysFree(SysId );
if (AppId != M_NULL) MappFree(AppId );
}
};
int MosMain(void)
{
PrintHeader();
try
{
MILObjectsStruture MILObjects;
MappAlloc(M_NULL, M_DEFAULT, &MILObjects.AppId);
MsysAlloc(MILObjects.AppId, M_SYSTEM_HOST, M_DEFAULT, M_DEFAULT, &MILObjects.SysId);
MgraAlloc(MILObjects.SysId, &MILObjects.ContextGraId);
GridInfoStruct GridInfo = ComputeGridParameters();
AnnotationStruct Annotation = ComputeAnnotationParameters(GridInfo);
MbufAlloc2d(MILObjects.SysId, Annotation.FullSizeX, Annotation.FullSizeY, 8+M_UNSIGNED, M_IMAGE+M_PROC+M_DISP, &MILObjects.FullImageId);
MbufChild2d(MILObjects.FullImageId, Annotation.LeftBorder, Annotation.TopBorder, Annotation.ImageSizeX, Annotation.ImageSizeY, &MILObjects.GridImageId);
MbufClear(MILObjects.FullImageId, BACKGROUND_COLOR);
MgraColor(MILObjects.ContextGraId, FOREGROUND_COLOR);
for (MIL_INT y = 0; y < GridInfo.NumSquaresY; ++y)
{
for (MIL_INT x = 0; x < GridInfo.NumSquaresX; ++x)
{
if ((x & 0x1) == (y & 0x1))
{
MgraRectFill(MILObjects.ContextGraId, MILObjects.GridImageId,
x * Annotation.PixelsPerSquareX, y * Annotation.PixelsPerSquareY,
(x+1) * Annotation.PixelsPerSquareX - 1, (y+1) * Annotation.PixelsPerSquareY - 1);
}
}
}
DrawThickRect(MILObjects.ContextGraId, MILObjects.GridImageId, BACKGROUND_COLOR,
static_cast<MIL_INT>(QUIET_ZONE_BORDER * Annotation.PixelsPerSquareX),
static_cast<MIL_INT>(QUIET_ZONE_BORDER * Annotation.PixelsPerSquareY),
0, 0, Annotation.ImageSizeX-1, Annotation.ImageSizeY-1);
AddFiducials(MILObjects.GridImageId, GridInfo, Annotation.PixelsPerSquareX, Annotation.PixelsPerSquareY);
if (DRAW_ANNOTATIONS)
DrawAnnotations(MILObjects.ContextGraId, MILObjects.FullImageId, GridInfo, Annotation);
MbufControl(MILObjects.FullImageId, M_RESOLUTION_X, DPI);
MbufControl(MILObjects.FullImageId, M_RESOLUTION_Y, DPI);
MbufExport(OUTPUT_GRID_NAME, OUTPUT_FILE_FORMAT, MILObjects.FullImageId);
MdispAlloc(MILObjects.SysId, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_WINDOWED, &MILObjects.DispId);
SetZoomFactor(MILObjects.DispId, Annotation.FullSizeX, Annotation.FullSizeY);
MdispSelect(MILObjects.DispId, MILObjects.FullImageId);
MosPrintf(MIL_TEXT("Image saved:\n"));
MosPrintf(MIL_TEXT("------------\n"));
MosPrintf(MIL_TEXT(" Name: '%s'\n"), OUTPUT_GRID_NAME);
MosPrintf(MIL_TEXT(" Size: %d x %d\n"), (int)Annotation.FullSizeX, (int)Annotation.FullSizeY);
MosPrintf(MIL_TEXT("\n"));
MosPrintf(MIL_TEXT("To print this image correctly:\n"));
MosPrintf(MIL_TEXT(" - Set your printer resolution to %d DPI or higher.\n"), (int)DPI);
MosPrintf(MIL_TEXT(" - Print with software that takes the DPI into account.\n"));
MosPrintf(MIL_TEXT(" - Disable any 'fit' or 'scale' option in the print dialog.\n"));
MosPrintf(MIL_TEXT(" - Verify the printed grid dimensions.\n"));
MosPrintf(MIL_TEXT("\n"));
MosPrintf(MIL_TEXT("Press <Enter> to end.\n"));
MosGetch();
}
catch (MIL_CONST_TEXT_PTR ErrorMessage)
{
MosPrintf(MIL_TEXT("\nERROR:\n %s.\n\n"), ErrorMessage);
MosPrintf(MIL_TEXT("Press <Enter> to end.\n"));
MosGetch();
}
return 0;
}