805 lines
32 KiB
C++
805 lines
32 KiB
C++
/***********************************************************************************************************************
|
|
*
|
|
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
|
|
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
|
|
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
|
|
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
|
|
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
|
|
* scope and manner of such use.
|
|
*
|
|
***********************************************************************************************************************/
|
|
/**
|
|
\file DemoFunctionalities.cpp
|
|
|
|
This file demonstrates numerous functionalities of HOOPS Publish.
|
|
|
|
***********************************************************************************************************************/
|
|
|
|
#define INITIALIZE_A3D_API
|
|
#define HOOPS_PRODUCT_PUBLISH_STANDARD
|
|
#include <A3DSDKIncludes.h>
|
|
#include <hoops_license.h>
|
|
#include "../common.hpp"
|
|
#include "../CommonInit.h"
|
|
|
|
#include <sstream>
|
|
#include <ostream>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
// default sample arguments:
|
|
// in visual c++: the current directory is set through properties to $OutDir, which is $(Platform)\$(Configuration)
|
|
// in linux: the current directory is supposed to be the same as this cpp file
|
|
#ifdef _MSC_VER
|
|
# define OUT_FILE SAMPLES_PUBLISH_GALLERY_DIRECTORY"\\sample_DemoFunctionalities.pdf"
|
|
# define POSTER_PATH SAMPLES_DATA_DIRECTORY"\\images\\pleaseactivate.bmp"
|
|
# define IN_BKIMAGE SAMPLES_PUBLISH_QUICKSTARTS_DIRECTORY"\\BackgroundImages\\Simple3_Letter_Blue_L.jpg"
|
|
# define IN_LOGOIMAGE SAMPLES_DATA_DIRECTORY"\\images\\logo_e.jpg"
|
|
# define IN_POSTER_IMAGE1 SAMPLES_DATA_DIRECTORY"\\images\\Carter_poster.jpg"
|
|
# define IN_3DFILE SAMPLES_DATA_DIRECTORY"\\prc\\Crank-Pulley.pdf"
|
|
# define IN_3DFILE2 SAMPLES_DATA_DIRECTORY"\\prc\\Crank-Valve.pdf"
|
|
# define IN_3DFILE3 SAMPLES_DATA_DIRECTORY"\\prc\\Crank-Instructions.prc"
|
|
# define IN_3DFILE4 SAMPLES_DATA_DIRECTORY"\\prc\\Carter.prc"
|
|
# define IN_MAPIMAGE SAMPLES_DATA_DIRECTORY"\\images\\colormap.jpg"
|
|
# define EXTRA_PAGE SAMPLES_DATA_DIRECTORY"\\pdf_templates\\DemoFuncTables.pdf"
|
|
# define ATTACHED_FILE SAMPLES_DATA_DIRECTORY"\\pdf_templates\\DemoFuncTables.xls"
|
|
#else
|
|
# define OUT_FILE SAMPLES_PUBLISH_GALLERY_DIRECTORY"/sample_DemoFunctionalities.pdf"
|
|
# define POSTER_PATH SAMPLES_DATA_DIRECTORY"/images/pleaseactivate.bmp"
|
|
# define IN_BKIMAGE SAMPLES_PUBLISH_QUICKSTARTS_DIRECTORY"/BackgroundImages/Simple3_Letter_Blue_L.jpg"
|
|
# define IN_LOGOIMAGE SAMPLES_DATA_DIRECTORY"/images/logo_e.jpg"
|
|
# define IN_POSTER_IMAGE1 SAMPLES_DATA_DIRECTORY"/images/Carter_poster.jpg"
|
|
# define IN_3DFILE SAMPLES_DATA_DIRECTORY"/prc/Crank-Pulley.pdf"
|
|
# define IN_3DFILE2 SAMPLES_DATA_DIRECTORY"/prc/Crank-Valve.pdf"
|
|
# define IN_3DFILE3 SAMPLES_DATA_DIRECTORY"/prc/Crank-Instructions.prc"
|
|
# define IN_3DFILE4 SAMPLES_DATA_DIRECTORY"/prc/Carter.prc"
|
|
# define IN_MAPIMAGE SAMPLES_DATA_DIRECTORY"/images/colormap.jpg"
|
|
# define EXTRA_PAGE SAMPLES_DATA_DIRECTORY"/pdf_templates/DemoFuncTables.pdf"
|
|
# define ATTACHED_FILE SAMPLES_DATA_DIRECTORY"/pdf_templates/DemoFuncTables.xls"
|
|
#endif
|
|
|
|
// rgb colors
|
|
#define COL_BLACK 0.0, 0.0, 0.0
|
|
#define COL_RED 1.0, 0.0, 0.0
|
|
#define COL_LIGHTGREY 0.4, 0.4, 0.4
|
|
#define COL_LIGHTBLUE 0.0, 0.5, 0.5
|
|
|
|
const size_t MAXSZFILENAME = 4096;
|
|
|
|
|
|
|
|
|
|
//######################################################################################################################
|
|
// writes a text line on the page
|
|
A3DStatus WriteTextString(A3DPDFDocument* pDoc, A3DPDFPage* pPage, A3DPDFEFontName eFontName, A3DInt32 iFontSize,
|
|
A3DDouble dR, A3DDouble dG, A3DDouble dB, const A3DUTF8Char* pcTextString,
|
|
A3DInt32 iPosLeft, A3DInt32 iPosBottom)
|
|
{
|
|
A3DStatus iRet = A3D_SUCCESS;
|
|
|
|
A3DPDFTextData sTextData;
|
|
A3D_INITIALIZE_DATA(A3DPDFTextData, sTextData);
|
|
|
|
sTextData.m_eFontName = eFontName;
|
|
sTextData.m_iFontSize = iFontSize;
|
|
sTextData.m_sColor.m_dRed = dR;
|
|
sTextData.m_sColor.m_dGreen = dG;
|
|
sTextData.m_sColor.m_dBlue = dB;
|
|
sTextData.m_pcTextString = const_cast<A3DUTF8Char*>(pcTextString);
|
|
A3DPDFText* pText = NULL;
|
|
CHECK_RET(A3DPDFTextCreate(pDoc, &sTextData, &pText));
|
|
|
|
CHECK_RET(A3DPDFPageInsertText(pPage, pText, iPosLeft, iPosBottom)); // iPosLeft, iPosBottom from the bottom left
|
|
|
|
return iRet;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
// displays an image on the page
|
|
A3DStatus WriteImage(A3DPDFDocument* pDoc, A3DPDFPage* pPage, const A3DUTF8Char* pcFileName,
|
|
int iLeft, int iBottom, int iRight, int iTop)
|
|
{
|
|
A3DStatus iRet = A3D_SUCCESS;
|
|
|
|
A3DPDFImage* pImage = NULL;
|
|
CHECK_RET(A3DPDFImageCreateFromFile(pDoc, pcFileName, kA3DPDFImageFormatUnknown, &pImage));
|
|
|
|
// positioning the object on the page
|
|
A3DPDFRectData sPos;
|
|
A3D_INITIALIZE_DATA(A3DPDFRectData, sPos);
|
|
|
|
// coordinates are from bottom left of the page
|
|
sPos.m_iLeft = iLeft; // lower left x
|
|
sPos.m_iBottom = iBottom; // lower left y
|
|
sPos.m_iRight = iRight; // upper right x
|
|
sPos.m_iTop = iTop; // upper right y
|
|
|
|
CHECK_RET(A3DPDFPageInsertImage2(pPage, pImage, &sPos));
|
|
|
|
return iRet;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
// writes a link on the page
|
|
A3DStatus WriteLink(A3DPDFDocument* pDoc, A3DPDFPage* pPage, A3DPDFELinkHighlightMode eHighlightingMode, A3DInt32 iBorderWidth,
|
|
A3DDouble dR, A3DDouble dG, A3DDouble dB,
|
|
int iLeft, int iBottom, int iRight, int iTop,
|
|
A3DPDFLink** ppLink)
|
|
{
|
|
A3DStatus iRet = A3D_SUCCESS;
|
|
*ppLink = NULL;
|
|
|
|
A3DPDFLinkData sLinkData;
|
|
A3D_INITIALIZE_DATA(A3DPDFLinkData, sLinkData);
|
|
|
|
sLinkData.m_eHighlightingMode = eHighlightingMode;
|
|
sLinkData.m_iBorderWidth = iBorderWidth;
|
|
sLinkData.m_sColor.m_dRed = dR;
|
|
sLinkData.m_sColor.m_dGreen = dG;
|
|
sLinkData.m_sColor.m_dBlue = dB;
|
|
CHECK_RET(A3DPDFLinkCreate(pDoc, &sLinkData, ppLink));
|
|
|
|
// positioning the object on the page
|
|
A3DPDFRectData sPos;
|
|
A3D_INITIALIZE_DATA(A3DPDFRectData, sPos);
|
|
|
|
// coordinates are from bottom left of the page
|
|
sPos.m_iLeft = iLeft; // lower left x
|
|
sPos.m_iBottom = iBottom; // lower left y
|
|
sPos.m_iRight = iRight ; // upper right x
|
|
sPos.m_iTop = iTop ; // upper right y
|
|
|
|
CHECK_RET(A3DPDFPageInsertLink(pPage, *ppLink, &sPos));
|
|
|
|
return iRet;
|
|
}
|
|
|
|
|
|
//######################################################################################################################
|
|
A3DStatus Create3DAnnot(A3DPDFDocument* pDoc,
|
|
const A3DUTF8Char* pcFileName,
|
|
A3DPDFImage* pPoster,
|
|
const A3DUTF8Char* pcInjsfile,
|
|
A3DPDFELighting eLighting, A3DPDFERenderingStyle eRenderingStyle,
|
|
bool bExplicitActivDesactiv,
|
|
A3DPDF3DArtwork** pp3DArtwork,
|
|
A3DPDF3DAnnot** pp3DAnnot,
|
|
A3DAsmModelFile** ppModelFile)
|
|
{
|
|
A3DStatus iRet = A3D_SUCCESS;
|
|
*pp3DAnnot = NULL;
|
|
*ppModelFile = NULL;
|
|
A3DPDF3DStream* pStream = NULL;
|
|
char tempfilename[1024];
|
|
|
|
// Publish 6.0 - Particularity when the input 3D model is stored in a PDF file. The functions to read the 3D data from the PDF
|
|
// are not the same as for other formats.
|
|
if(strstr(pcFileName, ".pdf") != NULL)
|
|
{
|
|
A3DStream3DPDFData* pStream3DPDFData;
|
|
A3DInt32 iNumStreams;
|
|
iRet = A3DGet3DPDFStreams(pcFileName, &pStream3DPDFData, &iNumStreams);
|
|
if(iRet!=A3D_SUCCESS || iNumStreams == 0)
|
|
return A3D_ERROR;
|
|
|
|
// a real use case might parse every streams in the input file. Here we just take the first one (pStream3DPDFData[0]).
|
|
|
|
// even an input PRC file must be read in memory and mapped into modelfile data structures
|
|
if(pStream3DPDFData[0].m_bIsPrc)
|
|
{
|
|
iRet = A3DAsmModelFileLoadFromPrcStream(pStream3DPDFData[0].m_acStream, pStream3DPDFData[0].m_uiStreamSize, NULL, ppModelFile);
|
|
if(iRet!=A3D_SUCCESS)
|
|
{
|
|
A3DGet3DPDFStreams(NULL, &pStream3DPDFData, &iNumStreams); // to clean up the array of stream data
|
|
return iRet;
|
|
}
|
|
}
|
|
// a U3D stream must first be stored as a physical file ; then 2 situations occur:
|
|
// 1. read and LOAD the physical file into a modelfile using the common A3DAsmModelFileLoadFromFile function, then transform the modelfile into a stream
|
|
// OR
|
|
// 2. read the physical file into a binary stream (not loaded into a modelfile) using A3DPDF3DStreamCreateFromFile function
|
|
// In this sample we illustrate the workflow 2.
|
|
else
|
|
{
|
|
sprintf(tempfilename, "%s.u3d", OUT_FILE);
|
|
FILE * pFile=NULL;
|
|
#ifdef _MSC_VER
|
|
errno_t ret = fopen_s(&pFile, tempfilename , "wb");
|
|
if(ret == 0 && pFile)
|
|
#else
|
|
pFile = fopen(tempfilename , "wb");
|
|
if(pFile)
|
|
#endif
|
|
{
|
|
fwrite(pStream3DPDFData[0].m_acStream, 1, pStream3DPDFData[0].m_uiStreamSize, pFile);
|
|
fclose(pFile);
|
|
}
|
|
|
|
// physical file to stream
|
|
CHECK_RET(A3DPDF3DStreamCreateFromFile(pDoc, tempfilename, false, &pStream));
|
|
|
|
// !!! the file will have to be disposed of afterwards
|
|
remove(tempfilename);
|
|
}
|
|
|
|
A3DGet3DPDFStreams(NULL, &pStream3DPDFData, &iNumStreams); // to clean up the array of stream data
|
|
}
|
|
|
|
// Load the physical file in a ModelFile data structure if not already done
|
|
if(pStream == NULL && *ppModelFile == NULL)
|
|
{
|
|
// reading the input CAD file; the file can be disposed of afterwards.
|
|
A3DRWParamsLoadData sReadParam;
|
|
A3D_INITIALIZE_DATA(A3DRWParamsLoadData, sReadParam);
|
|
|
|
sReadParam.m_sGeneral.m_bReadSolids = true;
|
|
sReadParam.m_sGeneral.m_bReadSurfaces = true;
|
|
sReadParam.m_sGeneral.m_bReadWireframes = true;
|
|
sReadParam.m_sGeneral.m_bReadPmis = true;
|
|
sReadParam.m_sGeneral.m_bReadAttributes = true;
|
|
sReadParam.m_sGeneral.m_bReadHiddenObjects = false;
|
|
sReadParam.m_sGeneral.m_bReadConstructionAndReferences = false;
|
|
sReadParam.m_sGeneral.m_bReadActiveFilter = true;
|
|
sReadParam.m_sGeneral.m_eReadingMode2D3D = kA3DRead_3D;
|
|
sReadParam.m_sGeneral.m_eReadGeomTessMode = kA3DReadGeomAndTess;
|
|
sReadParam.m_sGeneral.m_eDefaultUnit = kA3DUnitUnknown;
|
|
sReadParam.m_sPmi.m_bAlwaysSubstituteFont = false;
|
|
sReadParam.m_sPmi.m_pcSubstitutionFont = const_cast<A3DUTF8Char*>("Myriad CAD");
|
|
sReadParam.m_sTessellation.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
|
|
sReadParam.m_sMultiEntries.m_bLoadDefault = true;
|
|
sReadParam.m_sAssembly.m_bUseRootDirectory = true;
|
|
CHECK_RET(A3DAsmModelFileLoadFromFile(pcFileName, &sReadParam, ppModelFile));
|
|
}
|
|
|
|
if(*ppModelFile != NULL)
|
|
{
|
|
// whatever the input format, we store it as PRC in the output PDF
|
|
// creating the PRC stream from the model file that is going to be inserted into the PDF file
|
|
A3DRWParamsExportPrcData sParamsExportData;
|
|
A3D_INITIALIZE_DATA(A3DRWParamsExportPrcData, sParamsExportData);
|
|
|
|
CHECK_RET(A3DPDF3DStreamCreateFromModelFileAsPRC(pDoc, *ppModelFile, &sParamsExportData, &pStream, NULL));
|
|
}
|
|
|
|
if(pStream != NULL)
|
|
{
|
|
// creating the 3D artwork
|
|
*pp3DArtwork = NULL;
|
|
A3DPDF3DArtworkData2 s3DArtworkData;
|
|
A3D_INITIALIZE_DATA(A3DPDF3DArtworkData2, s3DArtworkData);
|
|
|
|
s3DArtworkData.m_pStream = pStream;
|
|
s3DArtworkData.m_sDisplaySectionData.m_bAddSectionCaps = true;
|
|
s3DArtworkData.m_pcJavaScriptFileName = const_cast<A3DUTF8Char*>(pcInjsfile);
|
|
CHECK_RET(A3DPDF3DArtworkCreate2(pDoc, &s3DArtworkData, pp3DArtwork));
|
|
|
|
A3DPDF3DAnnotData sAnnotData;
|
|
A3D_INITIALIZE_DATA(A3DPDF3DAnnotData, sAnnotData);
|
|
|
|
sAnnotData.m_bOpenModelTree = false;
|
|
sAnnotData.m_bShowToolbar = false;
|
|
sAnnotData.m_eLighting = eLighting;
|
|
sAnnotData.m_eRenderingStyle = eRenderingStyle;
|
|
sAnnotData.m_sBackgroundColor.m_dRed = 0.25;
|
|
sAnnotData.m_sBackgroundColor.m_dGreen = 0.25;
|
|
sAnnotData.m_sBackgroundColor.m_dBlue = 0.25;
|
|
sAnnotData.m_bTransparentBackground = false;
|
|
sAnnotData.m_eActivateWhen = bExplicitActivDesactiv ? kA3DPDFActivExplicitActivation : kA3DPDFActivPageOpened;
|
|
sAnnotData.m_eDesactivateWhen = bExplicitActivDesactiv ? kA3DPDFActivExplicitDesactivation : kA3DPDFActivPageClosed;
|
|
sAnnotData.m_iAppearanceBorderWidth = 0;
|
|
sAnnotData.m_pPosterImage = pPoster; // default poster automatically generated
|
|
sAnnotData.m_p3DArtwork = *pp3DArtwork;
|
|
|
|
CHECK_RET(A3DPDF3DAnnotCreate(pDoc, &sAnnotData, pp3DAnnot));
|
|
|
|
// cleaning up -- WARNING: DO NOT CALL THIS BEFORE inserting the 3D annot
|
|
//CHECK_RET(A3DAsmModelFileDelete(pModelFile));
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
|
|
//######################################################################################################################
|
|
// Helper functions to create a Table on PDF Page using API
|
|
|
|
#define NOSPAN 1
|
|
|
|
void CreateStyle(A3DInt32 fontSize, A3DUTF8Char const* const fontName,
|
|
A3DPDFRgbColorData* textColor, A3DPDFRgbColorData* borderColor, A3DPDFRgbColorData* bkColor,
|
|
A3DPDFETableTextHorizontalAlign hAlignment, A3DPDFETableTextVerticalAlign vAlignment,
|
|
A3DInt32 rowHeight, A3DInt32 columnWidth,
|
|
A3DInt32 bPadding, A3DInt32 lPadding, A3DInt32 rPadding, A3DInt32 tPadding,
|
|
A3DPDFTableStyleData& outStyle)
|
|
{
|
|
A3D_INITIALIZE_DATA(A3DPDFTableStyleData, outStyle);
|
|
outStyle.m_iFontSize = fontSize;
|
|
outStyle.m_pcFontName = const_cast<A3DUTF8Char*>(fontName);
|
|
outStyle.m_pTextColor = textColor;
|
|
outStyle.m_pBorderColor = borderColor;
|
|
outStyle.m_pBackgroundColor = bkColor;
|
|
outStyle.m_eHorizAlignment = hAlignment;
|
|
outStyle.m_eVertAlignment = vAlignment;
|
|
outStyle.m_iRowHeight = rowHeight;
|
|
outStyle.m_iColumnWidth = columnWidth;
|
|
outStyle.m_iPaddingBottom = bPadding;
|
|
outStyle.m_iPaddingLeft = lPadding;
|
|
outStyle.m_iPaddingRight = rPadding;
|
|
outStyle.m_iPaddingTop = tPadding;
|
|
}
|
|
|
|
// Creates a Cell entity and push it in Cells array
|
|
A3DStatus AddTableCellDesc(std::vector<A3DPDFTableCellDesc*>& aCells, A3DUns8 iRowSpan, A3DUns8 iColSpan, A3DUTF8Char const* const pcCellString, A3DPDFTableStyleData* pStyle)
|
|
{
|
|
A3DStatus iResult = A3D_SUCCESS;
|
|
A3DPDFTableCellDesc* pTableCellDesc = nullptr;
|
|
A3DPDFTableCellDescData sTableCellDescData;
|
|
A3D_INITIALIZE_DATA(A3DPDFTableCellDescData, sTableCellDescData);
|
|
sTableCellDescData.m_iRowSpan = iRowSpan;
|
|
sTableCellDescData.m_iColSpan = iColSpan;
|
|
sTableCellDescData.m_pcCellString = const_cast<A3DUTF8Char*>(pcCellString);
|
|
sTableCellDescData.m_pStyle = pStyle;
|
|
iResult = A3DPDFTableCellDescCreate(&sTableCellDescData, &pTableCellDesc);
|
|
if (iResult == A3D_SUCCESS)
|
|
aCells.push_back(pTableCellDesc);
|
|
return iResult;
|
|
}
|
|
|
|
// Creates a Row entity populated with cells, and push it in Rows array
|
|
A3DStatus AddTableRowDesc(std::vector<A3DPDFTableRowDesc*>& aRows, const std::vector<A3DPDFTableCellDesc*>& aCells, A3DPDFTableStyleData* pStyle)
|
|
{
|
|
A3DStatus iResult = A3D_SUCCESS;
|
|
A3DPDFTableRowDesc* pTableRowDesc = nullptr;
|
|
A3DPDFTableRowDescData sTableRowDescData;
|
|
A3D_INITIALIZE_DATA(A3DPDFTableRowDescData, sTableRowDescData);
|
|
sTableRowDescData.m_iNumberOfCells = static_cast<A3DUns32>(aCells.size());
|
|
sTableRowDescData.m_ppCells = (A3DPDFTableCellDesc**)malloc(aCells.size() * sizeof(A3DPDFTableCellDesc**));
|
|
for (size_t i = 0; i < aCells.size(); i++)
|
|
sTableRowDescData.m_ppCells[i] = aCells[i];
|
|
sTableRowDescData.m_pStyle = pStyle;
|
|
iResult = A3DPDFTableRowDescCreate(&sTableRowDescData, &pTableRowDesc);
|
|
if (iResult == A3D_SUCCESS)
|
|
aRows.push_back(pTableRowDesc);
|
|
return iResult;
|
|
}
|
|
|
|
// Creates a Table populated with rows
|
|
A3DStatus CreateTableDesc(A3DPDFDocument* pDoc, A3DPDFTable*& pTable, const std::vector<A3DPDFTableRowDesc*>& aRows, A3DPDFTableStyleData* pStyle)
|
|
{
|
|
A3DStatus iResult = A3D_SUCCESS;
|
|
pTable = nullptr;
|
|
A3DPDFTableDescData sTableDescData;
|
|
A3D_INITIALIZE_DATA(A3DPDFTableDescData, sTableDescData);
|
|
sTableDescData.m_iNumberOfRows = static_cast<A3DUns32>(aRows.size());
|
|
sTableDescData.m_ppRows = (A3DPDFTableRowDesc**)malloc(aRows.size() * A3DUns32(sizeof(A3DPDFTableRowDesc*)));
|
|
for (size_t i = 0; i < aRows.size(); i++)
|
|
sTableDescData.m_ppRows[i] = aRows[i];
|
|
sTableDescData.m_pStyle = pStyle;
|
|
iResult = A3DPDFTableCreateFromDesc(pDoc, &sTableDescData, &pTable);
|
|
return iResult;
|
|
}
|
|
|
|
A3DStatus BuildPDFDocument()
|
|
{
|
|
A3DStatus iRet = A3D_SUCCESS;
|
|
|
|
A3DInt32 nbpages = -1;
|
|
int indexpage = 0;
|
|
|
|
// creating a document
|
|
A3DPDFDocument* pDoc = NULL;
|
|
|
|
CHECK_RET(A3DPDFDocumentCreateEmpty(&pDoc));
|
|
|
|
if (pDoc != NULL)
|
|
{
|
|
// populating the document metadata
|
|
A3DPDFDocumentInformationData sInformationData;
|
|
A3D_INITIALIZE_DATA(A3DPDFDocumentInformationData, sInformationData);
|
|
|
|
sInformationData.m_pcTitle = const_cast<A3DUTF8Char*>("HOOPS Publish Functionalities");
|
|
sInformationData.m_pcCreator = const_cast<A3DUTF8Char*>("HOOPS Publish Sample Application");
|
|
sInformationData.m_pcSubject = const_cast<A3DUTF8Char*>("This sample shows miscellaneous functionalities of HOOPS Publish");
|
|
sInformationData.m_pcAuthor = const_cast<A3DUTF8Char*>("Tech Soft 3D");
|
|
CHECK_RET(A3DPDFDocumentSetInformation(pDoc, &sInformationData));
|
|
|
|
A3DPDFPage* pPage = NULL;
|
|
|
|
// creating a poster image to be used as a poster for 3D.
|
|
A3DPDFImage* pBlankImage = NULL;
|
|
A3DPDFImageCreateFromFile(pDoc, POSTER_PATH, kA3DPDFImageFormatUnknown, &pBlankImage);
|
|
|
|
// create page 1
|
|
A3DPDFPageData2 sPageData;
|
|
A3D_INITIALIZE_DATA(A3DPDFPageData2, sPageData);
|
|
|
|
sPageData.m_ePageOrientation = kA3DPDFPageLandscape;
|
|
sPageData.m_ePageSize = kA3DPDFPageLetter; // standard letter format: 612 x 792
|
|
int iPageWidth = 792, iPageHeight = 612;
|
|
CHECK_RET(A3DPDFDocumentAppendNewPage2(pDoc, &sPageData, &pPage));
|
|
|
|
if (pPage != NULL)
|
|
{
|
|
// all the posX and posY parameters for WriteImage are from the bottom left!
|
|
|
|
// background image
|
|
const int iBkImageRes = 150;
|
|
const int iBkImageW = 1648 * 72 / iBkImageRes;
|
|
const int iBkImageH = 1276 * 72 / iBkImageRes;
|
|
const int iBkLeft = 0; // lower left x
|
|
const int iBkBottom = 0; // lower left y
|
|
CHECK_RET(WriteImage(pDoc, pPage, IN_BKIMAGE, iBkLeft, iBkBottom, iBkLeft + iBkImageW, iBkBottom + iBkImageH));
|
|
|
|
// logo image
|
|
const int iLogoRes = 72;
|
|
// factor / 3 to reduce the size of the logo
|
|
const int iLogoW = (int)(195 * 72 / iLogoRes / 3);
|
|
const int iLogoH = (int)(219 * 72 / iLogoRes / 3);
|
|
const int iLogoLeft = 10; // lower left x
|
|
const int iLogoBottom = iPageHeight - 42 - iLogoH; // lower left y
|
|
CHECK_RET(WriteImage(pDoc, pPage, IN_LOGOIMAGE, iLogoLeft, iLogoBottom, iLogoLeft + iLogoW, iLogoBottom + iLogoH));
|
|
|
|
// title in black
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelveticaBold, 50, COL_BLACK,
|
|
"Crank", 250, iPageHeight - 103));
|
|
|
|
// header right line1 in light grey
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelveticaBold, 10, COL_LIGHTGREY,
|
|
"Emulate Manufacturing", iPageWidth - 150, iPageHeight - 60));
|
|
|
|
// header right line2 in light grey
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelvetica, 10, COL_LIGHTGREY,
|
|
"Tel: +44 123 456 789", iPageWidth - 150, iPageHeight - 70));
|
|
|
|
// header right line3 in light grey
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelvetica, 10, COL_LIGHTGREY,
|
|
"Fax: +44 123 467 890", iPageWidth - 150, iPageHeight - 80));
|
|
|
|
// header right line4 in light grey
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelvetica, 10, COL_LIGHTGREY,
|
|
"Email: sales@emulate-man.com", iPageWidth - 150, iPageHeight - 90));
|
|
|
|
// header right line5 in light grey
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelvetica, 10, COL_LIGHTGREY,
|
|
"www.emulate-man.com", iPageWidth - 150, iPageHeight - 100));
|
|
|
|
// bottom text in red
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelvetica, 20, COL_RED,
|
|
"Company Confidential: Do Not Redistribute", 200, 30));
|
|
|
|
A3DPDF3DAnnot* p3DAnnot = NULL;
|
|
A3DPDF3DArtwork* p3DArtwork = NULL;
|
|
A3DAsmModelFile* pModelFile = NULL;
|
|
iRet = Create3DAnnot(pDoc, IN_3DFILE3, pBlankImage, NULL,
|
|
kA3DPDFLightHeadlamp, kA3DPDFRenderingSolid, false,
|
|
&p3DArtwork, &p3DAnnot, &pModelFile);
|
|
|
|
if (p3DAnnot != NULL)
|
|
{
|
|
// position the 3D annotation in the page
|
|
A3DPDFRectData sPos;
|
|
A3D_INITIALIZE_DATA(A3DPDFRectData, sPos);
|
|
|
|
// coordinates are from bottom left of the page
|
|
sPos.m_iLeft = 150; // lower left x
|
|
sPos.m_iBottom = 100; // lower left y
|
|
sPos.m_iRight = iPageWidth - 150; // upper right x
|
|
sPos.m_iTop = iPageHeight - 145; // upper right y
|
|
CHECK_RET(A3DPDFPageInsert3DAnnot(pPage, p3DAnnot, &sPos));
|
|
|
|
// cleanup 3D modelfile
|
|
CHECK_RET(A3DAsmModelFileDelete(pModelFile));
|
|
}
|
|
|
|
indexpage++;
|
|
}
|
|
|
|
// import pages from PDF file (not template)
|
|
CHECK_RET(A3DPDFDocumentAppendPageFromPDFFileEx(pDoc, EXTRA_PAGE, false, &pPage));
|
|
|
|
// browse new pages. in this example, we know we want to insert a 3D model in the 2 first pages
|
|
CHECK_RET(A3DPDFDocumentGetNumberPages(pDoc, &nbpages));
|
|
|
|
int indexpageprev = indexpage;
|
|
for (indexpage = indexpageprev; indexpage < nbpages; indexpage++)
|
|
{
|
|
CHECK_RET(A3DPDFDocumentGetPage(pDoc, indexpage, &pPage));
|
|
|
|
if (pPage != NULL)
|
|
{
|
|
// we have to know the size of the imported pages
|
|
// for any reason, these excel generated PDF are in a box [-12, 583 / 12, 853]
|
|
//const int iPageWidth = 595, iPageHeight = 841;
|
|
// in this example, we know where we want to insert the 3D
|
|
A3DPDFRectData sPos;
|
|
A3D_INITIALIZE_DATA(A3DPDFRectData, sPos);
|
|
// coordinates are from bottom left of the page
|
|
sPos.m_iLeft = 44 - 12; // lower left x
|
|
sPos.m_iBottom = 36 + 12; // lower left y
|
|
sPos.m_iRight = 595 - 44 - 12; // upper right x
|
|
sPos.m_iTop = 400 + 12; // upper right y
|
|
|
|
A3DPDF3DAnnot* p3DAnnot = NULL;
|
|
A3DPDF3DArtwork* p3DArtwork = NULL;
|
|
A3DAsmModelFile* pModelFile = NULL;
|
|
|
|
// 3D only in first 2 pages
|
|
if (indexpage - indexpageprev == 0)
|
|
iRet = Create3DAnnot(pDoc, IN_3DFILE, pBlankImage, NULL,
|
|
kA3DPDFLightCADOptimized, kA3DPDFRenderingSolid, false,
|
|
&p3DArtwork, &p3DAnnot, &pModelFile);
|
|
else if (indexpage - indexpageprev == 1)
|
|
iRet = Create3DAnnot(pDoc, IN_3DFILE2, pBlankImage, NULL,
|
|
kA3DPDFLightCADOptimized, kA3DPDFRenderingSolid, false,
|
|
&p3DArtwork, &p3DAnnot, &pModelFile);
|
|
|
|
// position the 3D annotation in the page
|
|
if (p3DAnnot != NULL)
|
|
{
|
|
CHECK_RET(A3DPDFPageInsert3DAnnot(pPage, p3DAnnot, &sPos));
|
|
|
|
// cleanup 3D modelfile
|
|
if (pModelFile != NULL)
|
|
CHECK_RET(A3DAsmModelFileDelete(pModelFile));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
sPageData.m_ePageOrientation = kA3DPDFPagePortrait;
|
|
sPageData.m_ePageSize = kA3DPDFPageLetter; // standard letter format: 612 x 792
|
|
iPageWidth = 612;
|
|
iPageHeight = 792;
|
|
CHECK_RET(A3DPDFDocumentAppendNewPage2(pDoc, &sPageData, &pPage));
|
|
|
|
if (pPage != NULL)
|
|
{
|
|
// all the posX and posY parameters for WriteImage are from the bottom left!
|
|
|
|
// logo image
|
|
const int iLogoRes = 72;
|
|
// factor / 3 to reduce the size of the logo
|
|
const int iLogoW = (int)(195 * 72 / iLogoRes / 3);
|
|
const int iLogoH = (int)(219 * 72 / iLogoRes / 3);
|
|
const int iLogoLeft = 69; // lower left x
|
|
const int iLogoBottom = iPageHeight - 34 - iLogoH; // lower left y
|
|
CHECK_RET(WriteImage(pDoc, pPage, IN_LOGOIMAGE, iLogoLeft, iLogoBottom, iLogoLeft + iLogoW, iLogoBottom + iLogoH));
|
|
|
|
// link
|
|
A3DPDFLink* pLink = NULL;
|
|
CHECK_RET(WriteLink(pDoc, pPage, kA3DPDFLinkHighlightOutline, 0, COL_LIGHTBLUE,
|
|
iLogoLeft, iLogoBottom, iLogoLeft + iLogoW, iLogoBottom + iLogoH,
|
|
&pLink));
|
|
|
|
// set action on link
|
|
if (pLink != NULL)
|
|
{
|
|
A3DPDFAction* pAction = NULL;
|
|
A3DPDFActionLaunchURLData sActionData;
|
|
A3D_INITIALIZE_DATA(A3DPDFActionLaunchURLData, sActionData);
|
|
sActionData.m_pcURL = const_cast<A3DUTF8Char*>("http://www.techsoft3d.com/");
|
|
CHECK_RET(A3DPDFActionLaunchURLCreate(&sActionData, &pAction));
|
|
CHECK_RET(A3DPDFLinkAddAction(pLink, pAction));
|
|
}
|
|
|
|
// map image
|
|
const int iMapRes = 72;
|
|
// factor / 1.8 to reduce the size of the image
|
|
const int iMapH = (int)(309 * 72 / iMapRes / 1.8);
|
|
const int iMapW = (int)(204 * 72 / iMapRes / 1.8);
|
|
const int iMapLeft = 490; // lower left x
|
|
const int iMapBottom = iPageHeight - 195 - iMapH; // lower left y
|
|
CHECK_RET(WriteImage(pDoc, pPage, IN_MAPIMAGE, iMapLeft, iMapBottom, iMapLeft + iMapW, iMapBottom + iMapH));
|
|
|
|
// title in black
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelveticaBold, 20, COL_BLACK,
|
|
"Model Validation Report", 213, iPageHeight - 70));
|
|
|
|
// table title line
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelveticaBold, 12, COL_BLACK,
|
|
"Deviation Distribution", 230, iPageHeight - 520));
|
|
|
|
// table creation
|
|
|
|
A3DPDFTable* pTable = nullptr;
|
|
// table description: defined similar to html, with definitions of rows, cells, and colspan and rowpans for scenario with cells merged.
|
|
// styles (including cells widths and heigths) are defined at level of (by order of priority) table, then rows, then cells.
|
|
std::vector<A3DPDFTableCellDesc*> aCells;
|
|
std::vector<A3DPDFTableRowDesc*> aRows;
|
|
|
|
A3DPDFRgbColorData colorBlack;
|
|
A3D_INITIALIZE_DATA(A3DPDFRgbColorData, colorBlack);
|
|
colorBlack.m_dGreen = colorBlack.m_dBlue = colorBlack.m_dRed = 0.;
|
|
A3DPDFRgbColorData colorGreyLight;
|
|
A3D_INITIALIZE_DATA(A3DPDFRgbColorData, colorGreyLight);
|
|
colorGreyLight.m_dRed = colorGreyLight.m_dGreen = colorGreyLight.m_dBlue = 0.85; // GreyLight
|
|
|
|
A3DPDFTableStyleData sStyleTableRowHeader;
|
|
CreateStyle(10, "MyriadPro,Bold", &colorBlack, &colorBlack, &colorGreyLight, kA3DPDFTableAlignHCentered,
|
|
kA3DPDFTableAlignVMiddle, 12, 100, 0, 0, 0, 0, sStyleTableRowHeader);
|
|
A3DPDFTableStyleData sStyleTable;
|
|
CreateStyle(10, "MyriadPro", &colorBlack, &colorBlack, nullptr, kA3DPDFTableAlignHCentered,
|
|
kA3DPDFTableAlignVMiddle, 12, 100, 0, 0, 0, 0, sStyleTable);
|
|
|
|
//ROW 0 for Header - style defined at row level
|
|
aCells.clear();
|
|
AddTableCellDesc(aCells, NOSPAN, NOSPAN, "Deviation", nullptr);
|
|
AddTableCellDesc(aCells, NOSPAN, NOSPAN, "# of Points", nullptr);
|
|
AddTableCellDesc(aCells, NOSPAN, NOSPAN, "% of Total", nullptr);
|
|
AddTableRowDesc(aRows, aCells, &sStyleTableRowHeader);
|
|
|
|
// Rows with data - no specific style on row, style will be the one defined at table level
|
|
aCells.clear();
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "0.109", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "16903", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "33.9", nullptr));
|
|
CHECK_RET(AddTableRowDesc(aRows, aCells, nullptr));
|
|
|
|
aCells.clear();
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "0.218", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "5124", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "10.3", nullptr));
|
|
CHECK_RET(AddTableRowDesc(aRows, aCells, nullptr));
|
|
|
|
aCells.clear();
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "0.327", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "7811", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "15.6", nullptr));
|
|
CHECK_RET(AddTableRowDesc(aRows, aCells, nullptr));
|
|
|
|
aCells.clear();
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "0.436", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "7811", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "15.6", nullptr));
|
|
CHECK_RET(AddTableRowDesc(aRows, aCells, nullptr));
|
|
|
|
aCells.clear();
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "0.545", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "6605", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "13.2", nullptr));
|
|
CHECK_RET(AddTableRowDesc(aRows, aCells, nullptr));
|
|
|
|
aCells.clear();
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "0.654", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "1688", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "3.4", nullptr));
|
|
CHECK_RET(AddTableRowDesc(aRows, aCells, nullptr));
|
|
|
|
aCells.clear();
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "0.763", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "1279", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "2.6", nullptr));
|
|
CHECK_RET(AddTableRowDesc(aRows, aCells, nullptr));
|
|
|
|
aCells.clear();
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "0.872", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "1109", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "2.2", nullptr));
|
|
CHECK_RET(AddTableRowDesc(aRows, aCells, nullptr));
|
|
|
|
aCells.clear();
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "0.981", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "1035", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "2.1", nullptr));
|
|
CHECK_RET(AddTableRowDesc(aRows, aCells, nullptr));
|
|
|
|
aCells.clear();
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "1.09", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "565", nullptr));
|
|
CHECK_RET(AddTableCellDesc(aCells, NOSPAN, NOSPAN, "1.1", nullptr));
|
|
CHECK_RET(AddTableRowDesc(aRows, aCells, nullptr));
|
|
|
|
// table creation
|
|
CHECK_RET(CreateTableDesc(pDoc, pTable, aRows, &sStyleTable));
|
|
// 3 columns size 100 makes table size 300
|
|
int iLeft = (iPageWidth - 300) / 2;
|
|
CHECK_RET(A3DPDFPageInsertTable(pPage, pTable, iLeft, iPageHeight - 540));
|
|
|
|
// bottom text line
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelvetica, 10, COL_BLACK,
|
|
"Adden & Hart LLC., 123 ABC Way, Dublin, Ireland | +353.1.847.6324 | www.addenandhart.com", 93, iPageHeight - 780));
|
|
|
|
// creating a poster image to be used as a poster for 3D.
|
|
A3DPDFImage* pImage = NULL;
|
|
A3DPDFImageCreateFromFile(pDoc, IN_POSTER_IMAGE1, kA3DPDFImageFormatUnknown, &pImage);
|
|
|
|
// 3D model
|
|
A3DPDF3DAnnot* p3DAnnot = NULL;
|
|
A3DPDF3DArtwork* p3DArtwork = NULL;
|
|
A3DAsmModelFile* pModelFile = NULL;
|
|
iRet = Create3DAnnot(pDoc, IN_3DFILE4, pImage, NULL,
|
|
kA3DPDFLightCADOptimized, kA3DPDFRenderingSolidWireframe, true,
|
|
&p3DArtwork, &p3DAnnot, &pModelFile);
|
|
|
|
if (p3DAnnot != NULL)
|
|
{
|
|
// position the 3D annotation in the page
|
|
A3DPDFRectData sPos;
|
|
A3D_INITIALIZE_DATA(A3DPDFRectData, sPos);
|
|
|
|
// coordinates are from bottom left of the page
|
|
sPos.m_iLeft = 24; // lower left x
|
|
sPos.m_iBottom = iPageHeight - 455; // lower left y
|
|
sPos.m_iRight = 478; // upper right x
|
|
sPos.m_iTop = iPageHeight - 125; // upper right y
|
|
CHECK_RET(A3DPDFPageInsert3DAnnot(pPage, p3DAnnot, &sPos));
|
|
|
|
// cleanup 3D modelfile
|
|
CHECK_RET(A3DAsmModelFileDelete(pModelFile));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// add a page footer to each page except first one
|
|
// note that pages generated by external applications such as excel in this example
|
|
// might crop the page a little bit, hence difficulties in positioning the objects.
|
|
CHECK_RET(A3DPDFDocumentGetNumberPages(pDoc, &nbpages));
|
|
for (indexpage = 1; indexpage < nbpages; indexpage++)
|
|
{
|
|
CHECK_RET(A3DPDFDocumentGetPage(pDoc, indexpage, &pPage));
|
|
|
|
if (pPage != NULL)
|
|
{
|
|
A3DUTF8Char acPageTxt[2048];
|
|
sprintf(acPageTxt, "Page %i", indexpage);
|
|
CHECK_RET(WriteTextString(pDoc, pPage, kA3DPDFFontHelvetica, 8, COL_BLACK, acPageTxt, 10, 18));
|
|
}
|
|
}
|
|
|
|
|
|
// add properties to the document
|
|
|
|
/*
|
|
// setting passwords and permissions (please uncomment to try the feature)
|
|
CHECK_RET(A3DPDFDocumentSetPasswordSecurity(pDoc,
|
|
"myuserpassword", "myownerpassword",
|
|
kA3DPDFDocumentPermDocAssembly + kA3DPDFDocumentPermPrint,
|
|
kA3DPDFEncryptAll));
|
|
*/
|
|
|
|
// adding the file attachment
|
|
CHECK_RET(A3DPDFDocumentAddFileAttachment(pDoc, ATTACHED_FILE, "Excel file for measures"));
|
|
|
|
|
|
// end document
|
|
|
|
CHECK_RET(A3DPDFDocumentSaveEx(pDoc, kA3DPDFSaveFull|kA3DPDFSaveOptimized, OUT_FILE));
|
|
|
|
CHECK_RET(A3DPDFDocumentClose(pDoc));
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
|
|
|
|
//######################################################################################################################
|
|
// Main function
|
|
#ifdef _MSC_VER
|
|
int wmain(A3DInt32, A3DUniChar**)
|
|
#else
|
|
int main(int, A3DUTF8Char**)
|
|
#endif
|
|
{
|
|
#ifndef _MSC_VER
|
|
setenv("LC_NUMERIC", "en_US.UTF-8", 1); // Locally force locale
|
|
#endif
|
|
// init A3DLIB library - automatically handled init/terminate
|
|
A3DSDKHOOPSPublishLoader sHoopsPublishLoader(_T(HOOPS_BINARY_DIRECTORY), HOOPS_LICENSE);
|
|
CHECK_RET(sHoopsPublishLoader.m_eSDKStatus);
|
|
CHECK_RET(A3DDllSetCallbacksMemory(CheckMalloc, CheckFree));
|
|
|
|
// init HOOPS Publish related PDF library - automatically handled init/terminate
|
|
// do it only only once during the life of the application
|
|
CHECK_RET( sHoopsPublishLoader.InitPDFLib() );
|
|
|
|
// launch PDF treatment
|
|
A3DStatus iRet = BuildPDFDocument();
|
|
if (iRet != A3D_SUCCESS)
|
|
return iRet;
|
|
|
|
// Check memory allocations
|
|
return (int)ListLeaks();
|
|
}
|