CGM Objects Library
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
CgmObjects overview

Introduction

The purpose of this library is to read, write and modify ISO standard CGM files regardless of the profile. For more infomration on the CGM Standard refer to ISO/IEC 8632-1. The two key classes to understanding this Library are CCgmObjects and CCgmBaseObj.

The CCgmObjects class contains a list of Picture Elements that are read from a CGM file. This class also contains the CGM attributes for example, Metafile Description, Version, Vdc Extent, Color Table and Fontlist.

The CCgmBaseObj and derived classes are container objects for the individual graphical elements. The CCgmBaseObj will contain attributes common to all graphicsl elements, like line color, line width and fill color. The classes derived from will contain attributes unique to a particular class of element. For example CCgmPoly which is derived from CCgmBasObj is a container class for "poly" type elements like Polyline and Polybezier and will contain the points data along with common attributes inherited from CCgmBaseObj.

The CCgmObjects elements list may also contain Application Structures (CAppStruct) which is an elements list which can contain graphical elements and or other Application Structures in the case of nested APS.

Usage Examples

Load, Modify and Save a CGM File

 Copyright (c) 2008-2012, Larson Software Technology, Inc. 
 #include "CgmObjects.h"
 #include "CgmObj.h"
 #include "Utility\Color.h"

 using namespace std;
 using namespace Larson;


 // Recursivly count number of Application Structures in CCgmObjects elements list
 static void CountAps(CElementList* pElements, int* pnAps)
 {
    for (unsigned int i = 0; i < pElements->m_elements.size(); i++)
    {
            PicElement elem = pElements->m_elements[i];
            if (elem.type == PicElement::AppStruct)
            {
                    // filter out APS types other than "grobject" like "layer, "grnode" or other undefined APS types
                    if (elem.data.pAppStruct->m_type == L"grobject")
                    {
                            *pnAps += 1;
                    }

                    // Since APS can be nested, process children of this APS
                    CountAps(elem.data.pAppStruct, pnAps);
            }
    }
 }

 void example()
 {
    std::wstring inFile = L"allelm01.cgm";
    std::wstring outFile = L"allelm01_1.cgm";

    // create an application CConfig instance
    CConfig  *pConfig = new Larson::CConfig();

    // create a CgmObjects instance and Load the CGM file
    CCgmObjects* pCgmObjects = new CCgmObjects(pConfig, NULL);

    // Load the CGM file and return error list
    std::vector<CgmInError> errorList;
    int   error = pCgmObjects->LoadFile(inFile, 1, &errorList);

    // Count number of Application structures in CGM file
    int nAps = 0;
    CountAps(pCgmObjects->m_elements, &nAps);

    printf ("Metafile description %s\n", pCgmObjects->m_metafileDescription.c_str());
    printf ("Metafile version %d\n", pCgmObjects->m_metafileVersion);

    if (error) 
            return;

    for (int i = 0; i < (int)pCgmObjects->m_elements.size(); i++) 
    { 
            PicElement elem = pCgmObjects->m_elements[i]; 
            switch (elem.type)
            {
                    case graphical: 
                    {
                            // graphical element
                            CCgmBaseObj *pObj = elem.data.pObj;

                            if (pObj->m_nShape == CCgmBaseObj::text || pObj->m_nShape == CCgmBaseObj::restrictedText)
                            {
                                    printf ("Text %s\n", ((CCgmText*)pObj)->m_text.c_str());
                            }
                            else
                            {
                                    // make all other elements red
                                    pObj->m_lineColor = CColor(255, 0, 0, 255);
                                    pObj->m_fillColor = CColor(255, 0, 0, 255);
                            }
                    }
                    case APS:
                    {
                            // Application Structure
                            printf ("APS id %s\n", elem.data.pAppStruct->m_id);
                    }
            }
    }

    // write modified CGM file with default profile, vdcPrecision = 32 bit float, no compression
    pCgmObjects->Save(outFile, false, 2, 0, false);

    // destroy CCgmObjects and all of it's contents 
    delete pCgmObjects;
 }  

Load and Draw a CGM File

 Copyright (c) 2008-2012, Larson Software Technology, Inc. 
 #include "CgmObjects.h"
 #include "CgmObj.h"
 #include "Utility\Color.h"
 #include "DrawGDI.h"

 using namespace std;
 using namespace Larson;

 {
    std::wstring inFile = L"allelm01.cgm";
    std::wstring userFontsDir = L".";

    // given a Window (pWnd) get client window rect and device context
    CRect client;
    pWnd->GetClientRect(&client);
    CDC * pDC = pWnd->GetDC();

    Larson::CConfig * pConfig = new CConfig;

    // create a CgmObjects instance to hold the CGM
    CCgmObjects  *pCgmObjects = new CCgmObjects(pConfig);

    // Load CGM file
    pCgmObjects->LoadFile(inFile, 1);

    CDrawGDI *pDB = new CDrawGDI();

    // specify Windows Device Context
    pDB->setDisplay(pDC->hDC);

    pDB->open();
    pDB->clear();

    // scale to fit client window
    DRect viewport = DRect(client.left, client.top, client, client.bottom);

    // get CGM VDC extents
    DRect window = DRect(pCgmObjects->m_vdcExtent[0].x, pCgmObjects->m_vdcExtent[1].y, 
                                    pCgmObjects->m_vdcExtent[1].x, pCgmObjects->m_vdcExtent[0].y);

    double vdcWidth = window.Width();
    double vdcHeight = window.Height();
    double HRatio = vdcWidth / viewport.Width();
    double VRatio = vdcHeight / viewport.Height();

    Larson::DPoint vdcCenter = window.CenterPoint();
    if (HRatio < VRatio)
    {
            // Scale to fit X axis, Note this is done by Increasing Vdc extent 
            // to create blank space to left right or both sides of picture 
            window.left = vdcCenter.x - (viewport.Width()  * VRatio / 2);
            window.right = vdcCenter.x + (viewport.Width()  * VRatio / 2);
    }
    else
    {
            // Scale to fit Y axis
            window.bottom = vdcCenter.y - (viewport.Height() * HRatio / 2);
            window.top = vdcCenter.y + (viewport.Height() * HRatio / 2);
    }

    // Set the VDC to Device coordnates transform
    pDB->setTransform(&window, &viewport, &viewport, 0, CDrawBase::upperLeft);

    // Draw CGM elements
    pCgmObjects->Draw(pDB, false);

    pDB->flush();
    pDB->close();

    delete pConfig;
    delete pDB;
    delete pCgmObjects;
 }

Create CGM file

 #include "CgmObjects/CgmObjects.h"
 #include "CgmObjects/CgmObj.h"
 #include "CgmObjects/MakeCgmObjs.h"
 #include "Utility/Color.h"

    using namespace std;
    using namespace Larson;

    std::wstring outFile = L"allelm01_make.cgm";
    std::wstring profile = L"WebCGM";

    // make an application CConfig instance
    CConfig  *pConfig = new Larson::CConfig();

    // make a CgmObjects instance CGM objects
    CCgmObjects* pCgmObjects = new CCgmObjects(pConfig, NULL);

    // intialize metafile settings
    pCgmObjects->m_scalingMode = CCgmObjects::ScalingMode::scalingModeMetric;
    pCgmObjects->m_scalingFactor = 0.1;
    // metafile VDC extents
    pCgmObjects->m_vdcExtent[0] = Larson::DPoint(0., 0.);
    pCgmObjects->m_vdcExtent[1] = Larson::DPoint(1000., 1000.);

    pCgmObjects->m_backgroundColor = CColor(255,255,255,255);

    // initialize metafile color table
    pCgmObjects->m_colorTable[0].color =  CColor(255,255,255,255);
    pCgmObjects->m_colorTable[0].valid = 1;
    pCgmObjects->m_colorTable[1].color =  CColor(0,0,0,255);
    pCgmObjects->m_colorTable[1].valid = 1;

    // make a CGM attribute state list
    CCgmAttrState as;

    CCgmBaseObj *pObj = NULL;

    // change some attributes in state list
    as.fillColor = CColor(0,0,255,255);
    as.edgeColor = CColor(255,255,0,255);
    as.edgeVisible = CCgmBaseObj::edgeVisibleOn;
    as.characterHeight = 20;

    // make Restricted Text primitives and add each to CGM Objects elements list
    pCgmObjects->add(MakeCgmObjs::RestrictedText(450, 20, Larson::DPoint(25,85), true, L"ALLELM01; ATA v2.4;  ClrClass:c", pCgmObjects, &as));
    pCgmObjects->add(MakeCgmObjs::RestrictedText(410, 20, Larson::DPoint(25,55), true, L"NIST CGM Interpreter Test Suite", pCgmObjects, &as));
    pCgmObjects->add(MakeCgmObjs::RestrictedText(320, 20, Larson::DPoint(25,25), true, L"Release 3.0,  Sept 1998", pCgmObjects, &as));

    pCgmObjects->add(MakeCgmObjs::RestrictedText(90, 66, Larson::DPoint(460,300), true, L"TEXT", pCgmObjects, &as));

    // make Polyline primitive and add to CGM Objects elements list
    Larson::DPoint polyline[] = { Larson::DPoint(60,260), Larson::DPoint(140,340) };
    pCgmObjects->add(MakeCgmObjs::Polyline(&polyline[0], 2, pCgmObjects, &as));


    // make Disjoint Polyline (vectors) primitive and add to CGM Objects elements list
    Larson::DPoint disjoint[] = { Larson::DPoint(140,260), Larson::DPoint(170,340), Larson::DPoint(210,270), Larson::DPoint(240,340) };
    pCgmObjects->add(MakeCgmObjs::DisjointPolyline(&disjoint[0], 4, pCgmObjects, &as));

    // make Polymarker primitive and add to CGM Objects elements list
    Larson::DPoint polymarker[] = { Larson::DPoint(270,260), Larson::DPoint(300,300), Larson::DPoint(330,330) };
    pCgmObjects->add(MakeCgmObjs::Polymarker(&polymarker[0], 3, pCgmObjects, &as));

    // make Text primitive and add to CGM Objects elements list
    pCgmObjects->add(MakeCgmObjs::Text(Larson::DPoint(360,300), true, L"TEXT", pCgmObjects, &as));

    // make Text and an Append Text primitive and add to CGM Objects elements list
    pCgmObjects->add(MakeCgmObjs::Text(Larson::DPoint(560,300), false, L"T", pCgmObjects, &as));
    pCgmObjects->add(MakeCgmObjs::AppendText(true, L"EXT", pCgmObjects, &as));

    // Polygon point data
    Larson::DPoint polygon[] = { Larson::DPoint(660,300), Larson::DPoint(700,260), Larson::DPoint(740,300), Larson::DPoint(700,340) };
    pCgmObjects->add(MakeCgmObjs::Polygon(&polygon[0], 4, pCgmObjects, &as));

    // Polygon Set point data
    Larson::DPoint pgonset[] = { Larson::DPoint(760,300), Larson::DPoint(800,260), Larson::DPoint(840,300), Larson::DPoint(800,340) };

    // Polygon Set edge visibilities
    CCgmBaseObj::EdgeFlags edgeFlags[] = {
            CCgmBaseObj::edgeFlagVisible,
            CCgmBaseObj::edgeFlagInvisible,
            CCgmBaseObj::edgeFlagVisible,
            CCgmBaseObj::edgeFlagVisibleClose
    };

    // make Polygon Set primitive and add to CGM Objects elements list
    pCgmObjects->add(MakeCgmObjs::PolygonSet(&pgonset[0], 4, edgeFlags, pCgmObjects, &as));

    // 2 x 2 Cell array color data, each cell is 32 bits per pixel 
    unsigned long cellarray[] = { 0xff0000ff, 0xff00ff00, 0xffff0000, 0xff00ffff };

    // make Cell Array Set primitive and add to CGM Objects elements list
    pCgmObjects->add(MakeCgmObjs::CellArray(Larson::DPoint(870,330), Larson::DPoint(930,270), Larson::DPoint(930,330),
            2, 2, 32, cellarray, 0, pCgmObjects, &as));

    // make Rectangle primitive and add to CGM Objects elements list
    pCgmObjects->add(MakeCgmObjs::Rectangle(Larson::DPoint(70,370), Larson::DPoint(130,430), pCgmObjects, &as));

    pCgmObjects->add(MakeCgmObjs::Circle(Larson::DPoint(200,400), 40, pCgmObjects, &as));

    pCgmObjects->add(MakeCgmObjs::CircularArc3Pt(Larson::DPoint(270,430), Larson::DPoint(260,400), Larson::DPoint(270,370),
            CCgmBaseObj::arcCloseNone, pCgmObjects, &as));

    pCgmObjects->add(MakeCgmObjs::CircularArc3Pt(Larson::DPoint(370,430), Larson::DPoint(360,400), Larson::DPoint(370,370),
            CCgmBaseObj::arcClosePie, pCgmObjects, &as));

    pCgmObjects->add(MakeCgmObjs::CircularArcCenter(Larson::DPoint(500,400), Larson::DPoint(-50,0), Larson::DPoint(0,50),
            40, CCgmBaseObj::arcCloseNone, pCgmObjects, &as));

    pCgmObjects->add(MakeCgmObjs::CircularArcCenter(Larson::DPoint(600,400), Larson::DPoint(-50,0), Larson::DPoint(0,50),
            40, CCgmBaseObj::arcCloseChord, pCgmObjects, &as));

    pCgmObjects->add(MakeCgmObjs::Ellipse(Larson::DPoint(700,400), Larson::DPoint(650,400), Larson::DPoint(700,430),
            pCgmObjects, &as));

    pCgmObjects->add(MakeCgmObjs::EllipticalArc(Larson::DPoint(800,400), Larson::DPoint(750,400), Larson::DPoint(800,430),
            Larson::DPoint(0,30), Larson::DPoint(50,0), CCgmBaseObj::arcCloseNone, pCgmObjects, &as));

    pCgmObjects->add(MakeCgmObjs::EllipticalArc(Larson::DPoint(900,400), Larson::DPoint(850,400), Larson::DPoint(900,430),
            Larson::DPoint(0,30), Larson::DPoint(50,0), CCgmBaseObj::arcClosePie, pCgmObjects, &as));

    // make a 1 bit per pixel tile array with a single tile
    if(MakeCgmObjs::BeginTileArray(Larson::DPoint(100,900), CCgmBaseObj::cellPathDir0,
            CCgmBaseObj::lineProgressionDir270, 1, 1, 128, 128, 0.5, 0.5, 0, 0, 128, 128,
            pCgmObjects, &as) == CGMI_NO_ERROR)
    {
            if(MakeCgmObjs::BiTonalTile(CCgmBaseObj::tileCompressBitmap, 0, CColor(0,0,0,255),
                    CColor(255,255,255,255), NULL, (void*)tileColors, 2049, pCgmObjects, &as) == CGMI_NO_ERROR)
            {
                    pCgmObjects->add(MakeCgmObjs::EndTileArray(pCgmObjects, &as));
            }
    }

    // make a T6 compressed 1 bit per pixel tile array with a single tile
    if(MakeCgmObjs::BeginTileArray(Larson::DPoint(500,900), CCgmBaseObj::cellPathDir0,
            CCgmBaseObj::lineProgressionDir270, 1, 1, 1304, 1246, 5., 5., 0, 0, 1304, 1246,
            pCgmObjects, &as) == CGMI_NO_ERROR)
    {
            if(MakeCgmObjs::BiTonalTile(CCgmBaseObj::tileCompressT6, 0, CColor(255,0,0,255),
                    CColor(0,255,0,255), NULL, (void*)t2, 14464, pCgmObjects, &as) == CGMI_NO_ERROR)
            {
                    pCgmObjects->add(MakeCgmObjs::EndTileArray(pCgmObjects, &as));
            }
    }

    // write CGM file with profile, vdcPrecision = 32 bit float, no compression

    CCgmObjects::CGMSaveOptions options;
    CGMSaveOptionsInit(&options);
    options.profileId = "ATA GRAPHICS.GREXCHANGE";
    options.profileEdition = "2.5";
    options.description = L"'ColourClass:Colour''Source:Company XYZ, Inc'".

    pCgmObjects->Save(outFile, &options);

    // destroy CCgmObjects and all of it's contents 
    delete pCgmObjects;