3358 lines
115 KiB
C++
3358 lines
115 KiB
C++
|
/*
|
||
|
* NOTICE and LICENSE for Tecplot Input/Output Library (TecIO) - OpenFOAM
|
||
|
*
|
||
|
* Copyright (C) 1988-2009 Tecplot, Inc. All rights reserved worldwide.
|
||
|
*
|
||
|
* Tecplot hereby grants OpenCFD limited authority to distribute without
|
||
|
* alteration the source code to the Tecplot Input/Output library, known
|
||
|
* as TecIO, as part of its distribution of OpenFOAM and the
|
||
|
* OpenFOAM_to_Tecplot converter. Users of this converter are also hereby
|
||
|
* granted access to the TecIO source code, and may redistribute it for the
|
||
|
* purpose of maintaining the converter. However, no authority is granted
|
||
|
* to alter the TecIO source code in any form or manner.
|
||
|
*
|
||
|
* This limited grant of distribution does not supersede Tecplot, Inc.'s
|
||
|
* copyright in TecIO. Contact Tecplot, Inc. for further information.
|
||
|
*
|
||
|
* Tecplot, Inc.
|
||
|
* 3535 Factoria Blvd, Ste. 550
|
||
|
* Bellevue, WA 98006, USA
|
||
|
* Phone: +1 425 653 1200
|
||
|
* http://www.tecplot.com/
|
||
|
*
|
||
|
*/
|
||
|
#include "stdafx.h"
|
||
|
#include "MASTER.h"
|
||
|
#define TECPLOTENGINEMODULE
|
||
|
|
||
|
/*
|
||
|
******************************************************************
|
||
|
******************************************************************
|
||
|
******* ********
|
||
|
****** (C) 1988-2008 Tecplot, Inc. *******
|
||
|
******* ********
|
||
|
******************************************************************
|
||
|
******************************************************************
|
||
|
*/
|
||
|
|
||
|
#define DATAIO4MODULE
|
||
|
#include "GLOBAL.h"
|
||
|
#include "TASSERT.h"
|
||
|
#include "Q_UNICODE.h"
|
||
|
#include "ALLOC.h"
|
||
|
|
||
|
#include "AUXDATA.h"
|
||
|
#include "DATASET.h"
|
||
|
#include "FILESTREAM.h"
|
||
|
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
|
||
|
#include "GEOM2.h"
|
||
|
#include "GEOM.h"
|
||
|
#include "INPUT.h"
|
||
|
#include "SET.h"
|
||
|
#include "TEXT.h"
|
||
|
#include "DATAIO4.h"
|
||
|
#include "DATASET0.h"
|
||
|
|
||
|
#include "STRUTIL.h"
|
||
|
#include "ARRLIST.h"
|
||
|
#include "STRLIST.h"
|
||
|
#include "Q_MSG.h"
|
||
|
|
||
|
#if defined IRIS
|
||
|
#include <ieeefp.h>
|
||
|
#endif
|
||
|
|
||
|
using namespace tecplot::strutil;
|
||
|
|
||
|
#if !defined(TECPLOTKERNEL) && defined(MSWIN)
|
||
|
# pragma warning(disable : 4244)
|
||
|
#endif
|
||
|
|
||
|
/*END HEADER*/
|
||
|
|
||
|
/*
|
||
|
* This module contains mostly low level i/o functions.
|
||
|
*/
|
||
|
|
||
|
#if defined DECALPHA || defined COMPAQALPHA
|
||
|
#define _IEEE_FP_INEXACT
|
||
|
#define _IEEE_FP
|
||
|
#endif
|
||
|
|
||
|
#if defined SUN41
|
||
|
#define SEEK_SET 0
|
||
|
#define SEEK_CUR 1
|
||
|
#define SEEK_END 2
|
||
|
#endif
|
||
|
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
|
||
|
/**********************************************************************
|
||
|
**********************************************************************
|
||
|
********************** INPUT **************************
|
||
|
**********************************************************************
|
||
|
**********************************************************************/
|
||
|
|
||
|
static char FilterFloatChar(float X)
|
||
|
{
|
||
|
char C;
|
||
|
if (((X >= 32.0) && (X <= 127.0)) ||
|
||
|
((X >= 160.0) && (X <= 255.0)) ||
|
||
|
(X == 0.0))
|
||
|
C = (char)X;
|
||
|
else
|
||
|
C = '?';
|
||
|
return (C);
|
||
|
}
|
||
|
|
||
|
|
||
|
double GetNextValue(FileStream_s *FileStream,
|
||
|
FieldDataType_e FieldDataType,
|
||
|
double VMin,
|
||
|
double VMax,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
double X = 0.0;
|
||
|
|
||
|
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
|
||
|
REQUIRE(!(*IsOk) || VALID_FIELD_DATA_TYPE(FieldDataType));
|
||
|
REQUIRE(!(*IsOk) || VALID_REF(FileStream));
|
||
|
|
||
|
if (*IsOk)
|
||
|
{
|
||
|
switch (FieldDataType)
|
||
|
{
|
||
|
case FieldDataType_Float :
|
||
|
{
|
||
|
float XX;
|
||
|
|
||
|
*IsOk = (TP_FREAD(&XX, 4, 1, FileStream->File) == 1);
|
||
|
|
||
|
if (!FileStream->IsByteOrderNative)
|
||
|
REVERSE_4_BYTES(&XX);
|
||
|
|
||
|
if (*IsOk)
|
||
|
X = XX;
|
||
|
else
|
||
|
X = 0.0;
|
||
|
} break;
|
||
|
case FieldDataType_Double :
|
||
|
{
|
||
|
double XX;
|
||
|
|
||
|
*IsOk = (TP_FREAD(&XX, sizeof(double), 1, FileStream->File) == 1);
|
||
|
if (!FileStream->IsByteOrderNative)
|
||
|
REVERSE_8_BYTES(&XX);
|
||
|
|
||
|
if (*IsOk)
|
||
|
X = XX;
|
||
|
else
|
||
|
X = 0.0;
|
||
|
} break;
|
||
|
case FieldDataType_Int32 :
|
||
|
{
|
||
|
Int32_t L;
|
||
|
*IsOk = (TP_FREAD(&L, sizeof(Int32_t), 1, FileStream->File) == 1);
|
||
|
if (!FileStream->IsByteOrderNative)
|
||
|
REVERSE_4_BYTES(&L);
|
||
|
if (*IsOk)
|
||
|
X = (double)L;
|
||
|
} break;
|
||
|
case FieldDataType_Int16 :
|
||
|
{
|
||
|
Int16_t S;
|
||
|
*IsOk = (TP_FREAD(&S, sizeof(Int16_t), 1, FileStream->File) == 1);
|
||
|
if (!FileStream->IsByteOrderNative)
|
||
|
REVERSE_2_BYTES(&S);
|
||
|
if (*IsOk)
|
||
|
X = (double)S;
|
||
|
} break;
|
||
|
case FieldDataType_Byte :
|
||
|
{
|
||
|
Byte_t B;
|
||
|
*IsOk = (TP_FREAD(&B, sizeof(Byte_t), 1, FileStream->File) == 1);
|
||
|
if (*IsOk)
|
||
|
X = (double)B;
|
||
|
} break;
|
||
|
case FieldDataType_Bit :
|
||
|
{
|
||
|
/*
|
||
|
* Important note:
|
||
|
* Reading bit data a value at a time is only valid for a
|
||
|
* single bit value. If the file contains a block of more than
|
||
|
* one bit value and you attempt to read it a bit at a time it
|
||
|
* will not work as Tecplot does not buffer the read. In order
|
||
|
* to read a block of bits you must perform a block read.
|
||
|
*/
|
||
|
Byte_t B;
|
||
|
*IsOk = (TP_FREAD(&B, sizeof(Byte_t), 1, FileStream->File) == 1);
|
||
|
if (*IsOk)
|
||
|
X = (double)(B & (Byte_t)01);
|
||
|
} break;
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
|
||
|
if (*IsOk)
|
||
|
{
|
||
|
if ((X < VMin) || (X > VMax))
|
||
|
{
|
||
|
*IsOk = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return X;
|
||
|
}
|
||
|
|
||
|
|
||
|
LgIndex_t GetNextI(FileStream_s *FileStream,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
LgIndex_t I = 0;
|
||
|
|
||
|
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
|
||
|
REQUIRE(!(*IsOk) || (VALID_REF(FileStream) && VALID_REF(FileStream->File)));
|
||
|
|
||
|
if (*IsOk)
|
||
|
{
|
||
|
Int32_t Int32Val;
|
||
|
*IsOk = (TP_FREAD((void *) & Int32Val, 4, 1, FileStream->File) == 1);
|
||
|
if (!FileStream->IsByteOrderNative)
|
||
|
REVERSE_4_BYTES(&Int32Val);
|
||
|
|
||
|
I = Int32Val;
|
||
|
}
|
||
|
return I;
|
||
|
}
|
||
|
|
||
|
|
||
|
LgIndex_t GetIoFileInt(FileStream_s *FileStream,
|
||
|
short Version,
|
||
|
LgIndex_t IMin,
|
||
|
LgIndex_t IMax,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
LgIndex_t I = 0;
|
||
|
|
||
|
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
|
||
|
REQUIRE(!(*IsOk) || (0 < Version && Version <= TecplotBinaryFileVersion));
|
||
|
REQUIRE(!(*IsOk) || (VALID_REF(FileStream) && VALID_REF(FileStream->File)));
|
||
|
REQUIRE(!(*IsOk) || IMin <= IMax);
|
||
|
|
||
|
if (!(*IsOk))
|
||
|
return (0);
|
||
|
|
||
|
if (Version <= 63)
|
||
|
{
|
||
|
float X;
|
||
|
if (*IsOk)
|
||
|
{
|
||
|
X = (float)GetNextValue(FileStream, FieldDataType_Float,
|
||
|
(double)IMin - 1.0e-10,
|
||
|
(double)IMax + 1.0e-10, IsOk);
|
||
|
if (*IsOk)
|
||
|
{
|
||
|
if (ABS(X) < (float)MAXINDEX)
|
||
|
I = (LgIndex_t)X;
|
||
|
else
|
||
|
*IsOk = FALSE;
|
||
|
}
|
||
|
else
|
||
|
*IsOk = FALSE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
I = GetNextI(FileStream, IsOk);
|
||
|
}
|
||
|
|
||
|
if ((I < IMin) || (I > IMax))
|
||
|
*IsOk = FALSE;
|
||
|
|
||
|
return (I);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Basically this is "realloc" but apparently "realloc" doesn't behave reliably
|
||
|
* on all platforms.
|
||
|
*/
|
||
|
static Boolean_t ReallocString(char **String,
|
||
|
LgIndex_t NewLength)
|
||
|
{
|
||
|
Boolean_t IsOk;
|
||
|
char *NewString;
|
||
|
|
||
|
REQUIRE(VALID_REF(String));
|
||
|
REQUIRE(*String == NULL || VALID_REF(*String));
|
||
|
REQUIRE((*String != NULL && NewLength >= (LgIndex_t)strlen(*String)) ||
|
||
|
(*String == NULL && NewLength >= 0));
|
||
|
|
||
|
NewString = ALLOC_ARRAY(NewLength + 1, char, "reallocated string");
|
||
|
IsOk = (NewString != NULL);
|
||
|
if (IsOk)
|
||
|
{
|
||
|
if (*String == NULL)
|
||
|
{
|
||
|
NewString[0] = '\0';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
strcpy(NewString, *String);
|
||
|
FREE_ARRAY(*String, "old string");
|
||
|
}
|
||
|
*String = NewString;
|
||
|
}
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
ENSURE(IMPLICATION(IsOk, VALID_REF(*String)));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Reads a string from all versions of a binary plt file.
|
||
|
*
|
||
|
* param FileStream
|
||
|
* Open file stream positioned at the string to read.
|
||
|
* param IVersion
|
||
|
* Binary file version number.
|
||
|
* param MaxCharacters
|
||
|
* IVersion < 63
|
||
|
* This value is exactly the number of characters (actually floats, each
|
||
|
* one representing a character's ordinal value) to read from the file.
|
||
|
* IVersion >= 63 and ProcessData == TRUE
|
||
|
* If non-zero, this value represents the largest string to be returned.
|
||
|
* In other words, larger strings are read from the file but an allocated
|
||
|
* string of up to MaxCharacters is returned. A zero value indicates that
|
||
|
* the string size is unlimited and determined only by the actual length
|
||
|
* of the string in the file.
|
||
|
* param TargetStr
|
||
|
* Pointer to hold the allocated string if ProcessData == TRUE.
|
||
|
* param ProcessData
|
||
|
* Indicates if the read string should be retrieved.
|
||
|
*
|
||
|
* return
|
||
|
* TRUE if the read was successful with an allocated string *TargetStr
|
||
|
* containing the string read (no larger than requested or necessary),
|
||
|
* FALSE otherwise.
|
||
|
*/
|
||
|
Boolean_t ReadInString(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
int MaxCharacters,
|
||
|
char **TargetStr,
|
||
|
Boolean_t ProcessData)
|
||
|
{
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
|
||
|
REQUIRE(IMPLICATION(IVersion < 63 || ProcessData, MaxCharacters >= 0));
|
||
|
REQUIRE(IMPLICATION(ProcessData, VALID_REF(TargetStr)));
|
||
|
REQUIRE(VALID_BOOLEAN(ProcessData));
|
||
|
|
||
|
if (IVersion < 63)
|
||
|
{
|
||
|
/*
|
||
|
* One word per character. Read Exactly "MaxCharacters" number of words.
|
||
|
*/
|
||
|
float X;
|
||
|
|
||
|
if (ProcessData)
|
||
|
{
|
||
|
*TargetStr = ALLOC_ARRAY(MaxCharacters + 1, char, "target string");
|
||
|
IsOk = (*TargetStr != NULL);
|
||
|
}
|
||
|
|
||
|
if (IsOk)
|
||
|
{
|
||
|
LgIndex_t I;
|
||
|
for (I = 0; IsOk && I < MaxCharacters; I++)
|
||
|
{
|
||
|
X = (float)GetNextValue(FileStream, FieldDataType_Float, 0.0, 127.0, &IsOk);
|
||
|
if (!IsOk)
|
||
|
break;
|
||
|
if (ProcessData)
|
||
|
(*TargetStr)[I] = FilterFloatChar(X);
|
||
|
}
|
||
|
if (ProcessData)
|
||
|
(*TargetStr)[I] = '\0';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ErrMsg(translate("Cannot allocate memory for string during read",
|
||
|
"'string' meaning the computer science data type"));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#define MAX_STRBUFFER_LEN 4095
|
||
|
static char StrBuffer[MAX_STRBUFFER_LEN+1];
|
||
|
LgIndex_t StrBufferLen = 0;
|
||
|
LgIndex_t TargetStrLen = 0;
|
||
|
LgIndex_t I = 0;
|
||
|
LgIndex_t CharValue = 0;
|
||
|
|
||
|
if (ProcessData)
|
||
|
*TargetStr = NULL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
CharValue = GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
|
||
|
if (IsOk && ProcessData)
|
||
|
{
|
||
|
/* massage the character if necessary */
|
||
|
if ((CharValue < 32 && CharValue != '\0' && CharValue != '\n') ||
|
||
|
(CharValue >= 128 && CharValue < 160))
|
||
|
CharValue = ' ';
|
||
|
|
||
|
/*
|
||
|
* if the limit is not exceded, stuff the
|
||
|
* character into the buffer
|
||
|
*/
|
||
|
if (CharValue != '\0' &&
|
||
|
(I < MaxCharacters || MaxCharacters == 0))
|
||
|
{
|
||
|
StrBuffer[StrBufferLen] = (char)CharValue;
|
||
|
StrBufferLen++;
|
||
|
}
|
||
|
|
||
|
if (CharValue == '\0' ||
|
||
|
StrBufferLen == MAX_STRBUFFER_LEN)
|
||
|
{
|
||
|
if (StrBufferLen != 0 || *TargetStr == NULL)
|
||
|
{
|
||
|
StrBuffer[StrBufferLen] = '\0';
|
||
|
TargetStrLen += StrBufferLen;
|
||
|
IsOk = ReallocString(TargetStr, TargetStrLen);
|
||
|
if (IsOk)
|
||
|
strcat(*TargetStr, StrBuffer);
|
||
|
StrBufferLen = 0; /* reset the string buffer */
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
I++;
|
||
|
}
|
||
|
while (IsOk && (char)CharValue != '\0');
|
||
|
|
||
|
/* if we failed cleanup if necessary */
|
||
|
if (!IsOk &&
|
||
|
ProcessData &&
|
||
|
*TargetStr != NULL)
|
||
|
{
|
||
|
FREE_ARRAY(*TargetStr, "failed read string");
|
||
|
*TargetStr = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ENSURE(IMPLICATION(ProcessData,
|
||
|
(VALID_REF(*TargetStr) || *TargetStr == NULL)));
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return (IsOk);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
static void ReadDoubleBlock(FileStream_s *FileStream,
|
||
|
Boolean_t DoRead,
|
||
|
double *Buffer,
|
||
|
LgIndex_t StartIndex,
|
||
|
LgIndex_t NumValues,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
if (DoRead)
|
||
|
{
|
||
|
double *DPtr = Buffer + StartIndex;
|
||
|
*IsOk = (TP_FREAD(DPtr, sizeof(double), NumValues, FileStream->File) == (size_t)NumValues);
|
||
|
if (!FileStream->IsByteOrderNative && *IsOk)
|
||
|
{
|
||
|
LgIndex_t N;
|
||
|
for (N = 0; N < NumValues; N++)
|
||
|
REVERSE_8_BYTES(&DPtr[N]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(double), SEEK_CUR) == 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
static void ReadFloatBlock(FileStream_s *FileStream,
|
||
|
Boolean_t DoRead,
|
||
|
float *Buffer,
|
||
|
LgIndex_t StartIndex,
|
||
|
LgIndex_t NumValues,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
if (DoRead)
|
||
|
{
|
||
|
float *FPtr = Buffer + StartIndex;
|
||
|
*IsOk = (TP_FREAD(FPtr, sizeof(float), NumValues, FileStream->File) == (size_t)NumValues);
|
||
|
if (!FileStream->IsByteOrderNative && *IsOk)
|
||
|
{
|
||
|
LgIndex_t N;
|
||
|
for (N = 0; N < NumValues; N++)
|
||
|
REVERSE_4_BYTES(&FPtr[N]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(float), SEEK_CUR) == 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
static void ReadBitBlock(FileStream_s *FileStream,
|
||
|
Boolean_t DoRead,
|
||
|
Byte_t *Buffer,
|
||
|
LgIndex_t NumValues,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
/*
|
||
|
* Do not allow reading of bit values if startindex is not 0.
|
||
|
* (This means geometries cannot use bit data.
|
||
|
*/
|
||
|
LgIndex_t NumBytes = (NumValues + 7) / 8;
|
||
|
if (DoRead)
|
||
|
{
|
||
|
*IsOk = (TP_FREAD(Buffer,
|
||
|
sizeof(Byte_t),
|
||
|
NumBytes,
|
||
|
FileStream->File) == (size_t)NumBytes);
|
||
|
}
|
||
|
else
|
||
|
*IsOk = (TP_FSEEK(FileStream->File, NumBytes * sizeof(Byte_t), SEEK_CUR) == 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
void ReadByteBlock(FileStream_s *FileStream,
|
||
|
Boolean_t DoRead,
|
||
|
Byte_t *Buffer,
|
||
|
HgIndex_t StartIndex,
|
||
|
HgIndex_t NumValues,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
if (DoRead)
|
||
|
{
|
||
|
*IsOk = (TP_FREAD(Buffer + StartIndex,
|
||
|
sizeof(Byte_t),
|
||
|
NumValues,
|
||
|
FileStream->File) == (size_t)NumValues);
|
||
|
}
|
||
|
else
|
||
|
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Byte_t), SEEK_CUR) == 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
void ReadInt16Block(FileStream_s *FileStream,
|
||
|
Boolean_t DoRead,
|
||
|
Int16_t *Buffer,
|
||
|
HgIndex_t StartIndex,
|
||
|
HgIndex_t NumValues,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
if (DoRead)
|
||
|
{
|
||
|
Int16_t *IntPtr = Buffer + StartIndex;
|
||
|
*IsOk = (TP_FREAD(IntPtr,
|
||
|
sizeof(Int16_t),
|
||
|
NumValues,
|
||
|
FileStream->File) == (size_t)NumValues);
|
||
|
|
||
|
if (!FileStream->IsByteOrderNative && *IsOk)
|
||
|
{
|
||
|
LgIndex_t N;
|
||
|
for (N = 0; N < NumValues; N++)
|
||
|
REVERSE_2_BYTES(&IntPtr[N]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int16_t), SEEK_CUR) == 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
void ReadInt16BlockToInt32(FileStream_s *FileStream,
|
||
|
Boolean_t DoRead,
|
||
|
Int32_t *Buffer,
|
||
|
HgIndex_t StartIndex,
|
||
|
HgIndex_t NumValues,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(FileStream));
|
||
|
REQUIRE(VALID_BOOLEAN(DoRead));
|
||
|
REQUIRE(VALID_REF(Buffer));
|
||
|
REQUIRE(StartIndex >= 0);
|
||
|
REQUIRE(NumValues >= 0);
|
||
|
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
|
||
|
|
||
|
if (DoRead)
|
||
|
{
|
||
|
HgIndex_t EndIndex = StartIndex + NumValues;
|
||
|
for (HgIndex_t ValueIndex = StartIndex; *IsOk && ValueIndex < EndIndex; ValueIndex++)
|
||
|
{
|
||
|
Int16_t Value;
|
||
|
*IsOk = (TP_FREAD(&Value, sizeof(Int16_t), 1, FileStream->File) == 1);
|
||
|
if (!FileStream->IsByteOrderNative && *IsOk)
|
||
|
REVERSE_2_BYTES(&Value);
|
||
|
Buffer[ValueIndex] = (Int32_t)Value;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int16_t), SEEK_CUR) == 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
void ReadInt32Block(FileStream_s *FileStream,
|
||
|
Boolean_t DoRead,
|
||
|
Int32_t *Buffer,
|
||
|
HgIndex_t StartIndex,
|
||
|
HgIndex_t NumValues,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
if (DoRead)
|
||
|
{
|
||
|
Int32_t *IntPtr = Buffer + StartIndex;
|
||
|
*IsOk = (TP_FREAD(IntPtr,
|
||
|
sizeof(Int32_t),
|
||
|
NumValues,
|
||
|
FileStream->File) == (size_t)NumValues);
|
||
|
|
||
|
if (!FileStream->IsByteOrderNative && *IsOk)
|
||
|
{
|
||
|
LgIndex_t N;
|
||
|
for (N = 0; N < NumValues; N++)
|
||
|
REVERSE_4_BYTES(&IntPtr[N]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int32_t), SEEK_CUR) == 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
void ReadPureBlock(FileStream_s *FileStream,
|
||
|
Boolean_t DoRead,
|
||
|
void *Buffer,
|
||
|
FieldDataType_e FieldDataType,
|
||
|
HgIndex_t StartIndex,
|
||
|
HgIndex_t NumValues,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(VALID_BOOLEAN(DoRead));
|
||
|
REQUIRE(!DoRead || VALID_REF(Buffer));
|
||
|
REQUIRE(VALID_FIELD_DATA_TYPE(FieldDataType));
|
||
|
REQUIRE(StartIndex >= 0);
|
||
|
REQUIRE(NumValues >= 0);
|
||
|
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
|
||
|
|
||
|
switch (FieldDataType)
|
||
|
{
|
||
|
case FieldDataType_Float :
|
||
|
{
|
||
|
ReadFloatBlock(FileStream,
|
||
|
DoRead,
|
||
|
(float *)Buffer,
|
||
|
StartIndex,
|
||
|
NumValues,
|
||
|
IsOk);
|
||
|
} break;
|
||
|
case FieldDataType_Double :
|
||
|
{
|
||
|
ReadDoubleBlock(FileStream,
|
||
|
DoRead,
|
||
|
(double *)Buffer,
|
||
|
StartIndex,
|
||
|
NumValues,
|
||
|
IsOk);
|
||
|
} break;
|
||
|
case FieldDataType_Bit :
|
||
|
{
|
||
|
if (StartIndex != 0)
|
||
|
{
|
||
|
ErrMsg(translate("Internal Error: Attempt to read bit data at non-zero offset",
|
||
|
"see Tecplot User's manual for a definition of 'bit' data"));
|
||
|
*IsOk = FALSE;
|
||
|
}
|
||
|
else
|
||
|
ReadBitBlock(FileStream,
|
||
|
DoRead,
|
||
|
(Byte_t *)Buffer,
|
||
|
NumValues,
|
||
|
IsOk);
|
||
|
} break;
|
||
|
case FieldDataType_Byte :
|
||
|
{
|
||
|
ReadByteBlock(FileStream,
|
||
|
DoRead,
|
||
|
(Byte_t *)Buffer,
|
||
|
StartIndex,
|
||
|
NumValues,
|
||
|
IsOk);
|
||
|
} break;
|
||
|
case FieldDataType_Int16 :
|
||
|
{
|
||
|
ReadInt16Block(FileStream,
|
||
|
DoRead,
|
||
|
(Int16_t *)Buffer,
|
||
|
StartIndex,
|
||
|
NumValues,
|
||
|
IsOk);
|
||
|
} break;
|
||
|
case FieldDataType_Int32 :
|
||
|
{
|
||
|
ReadInt32Block(FileStream,
|
||
|
DoRead,
|
||
|
(Int32_t *)Buffer,
|
||
|
StartIndex,
|
||
|
NumValues,
|
||
|
IsOk);
|
||
|
} break;
|
||
|
case FieldDataType_IJKFunction : /* Not used yet */
|
||
|
case FieldDataType_Int64 : /* Not used yet */
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
ENSURE(VALID_BOOLEAN(*IsOk));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
void ReadBlock(FileStream_s *FileStream,
|
||
|
FieldData_pa FieldData,
|
||
|
Boolean_t DoRead,
|
||
|
FieldDataType_e FieldDataTypeInFile,
|
||
|
HgIndex_t StartIndex,
|
||
|
HgIndex_t EndIndex,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
|
||
|
REQUIRE(IMPLICATION(IsOk, VALID_REF(FileStream)));
|
||
|
REQUIRE(IMPLICATION(IsOk, VALID_FIELD_DATA_TYPE(FieldDataTypeInFile)));
|
||
|
REQUIRE(VALID_BOOLEAN(DoRead));
|
||
|
REQUIRE(IMPLICATION(DoRead, VALID_REF(FieldData)));
|
||
|
|
||
|
/*
|
||
|
* Bit data is packed into bytes. Since Tecplot doesn't buffer reads it can
|
||
|
* not perform bit by bit value reads and therefore must only perform block
|
||
|
* reads of bit data.
|
||
|
*/
|
||
|
Boolean_t ReadByBlock = IMPLICATION(DoRead, GetFieldDataType(FieldData) == FieldDataTypeInFile);
|
||
|
REQUIRE(ReadByBlock || (FieldDataTypeInFile != FieldDataType_Bit));
|
||
|
|
||
|
if (*IsOk)
|
||
|
{
|
||
|
LgIndex_t NumValues = EndIndex - StartIndex + 1;
|
||
|
if (ReadByBlock)
|
||
|
{
|
||
|
void *data_array;
|
||
|
if (DoRead)
|
||
|
data_array = GetFieldDataVoidPtr(FieldData);
|
||
|
else
|
||
|
data_array = NULL;
|
||
|
ReadPureBlock(FileStream,
|
||
|
DoRead,
|
||
|
data_array,
|
||
|
FieldDataTypeInFile,
|
||
|
StartIndex,
|
||
|
NumValues,
|
||
|
IsOk);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LgIndex_t N;
|
||
|
for (N = 0; *IsOk && (N < NumValues); N++)
|
||
|
{
|
||
|
double D = GetNextValue(FileStream, FieldDataTypeInFile, -LARGEDOUBLE, LARGEDOUBLE, IsOk);
|
||
|
if (DoRead)
|
||
|
SetFieldValue(FieldData, N + StartIndex, D);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
void ReadClassicOrderedCCBlock(FileStream_s *DataFileStream,
|
||
|
FieldData_pa FieldData,
|
||
|
FieldDataType_e FieldDataTypeInFile,
|
||
|
LgIndex_t NumIPtsInFile,
|
||
|
LgIndex_t NumJPtsInFile,
|
||
|
LgIndex_t NumKPtsInFile,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
REQUIRE(IMPLICATION(*IsOk, VALID_REF(DataFileStream)));
|
||
|
REQUIRE(IMPLICATION(*IsOk, VALID_FIELD_DATA_TYPE(FieldDataTypeInFile)));
|
||
|
REQUIRE(VALID_REF(FieldData));
|
||
|
REQUIRE(NumIPtsInFile >= 0);
|
||
|
REQUIRE(NumJPtsInFile >= 0);
|
||
|
REQUIRE(NumKPtsInFile >= 0);
|
||
|
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
|
||
|
|
||
|
if (*IsOk)
|
||
|
{
|
||
|
LgIndex_t J, K;
|
||
|
LgIndex_t NumIJPts = NumIPtsInFile * NumJPtsInFile;
|
||
|
LgIndex_t IEnd = MAX(NumIPtsInFile - 1, 1);
|
||
|
LgIndex_t JEnd = MAX(NumJPtsInFile - 1, 1);
|
||
|
LgIndex_t KEnd = MAX(NumKPtsInFile - 1, 1);
|
||
|
LgIndex_t NumValues = (IEnd * JEnd * KEnd);
|
||
|
Boolean_t IsLinear = ((NumJPtsInFile == 1 && NumKPtsInFile == 1) ||
|
||
|
(NumIPtsInFile == 1 && NumKPtsInFile == 1) ||
|
||
|
(NumIPtsInFile == 1 && NumJPtsInFile == 1));
|
||
|
if (IsLinear)
|
||
|
ReadBlock(DataFileStream, FieldData, TRUE, FieldDataTypeInFile,
|
||
|
0, NumValues - 1, IsOk);
|
||
|
else
|
||
|
for (K = 0; K < KEnd && IsOk; K++)
|
||
|
for (J = 0; J < JEnd && IsOk; J++)
|
||
|
{
|
||
|
LgIndex_t CellIndex = 0 + (J * NumIPtsInFile) + (K * NumIJPts);
|
||
|
ReadBlock(DataFileStream, FieldData, TRUE, FieldDataTypeInFile,
|
||
|
CellIndex, CellIndex + IEnd - 1, IsOk);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(*IsOk));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
static void AdjustCustomColor(short IVersion,
|
||
|
ColorIndex_t *BColor)
|
||
|
{
|
||
|
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
|
||
|
REQUIRE(VALID_REF(BColor));
|
||
|
|
||
|
if ((IVersion < 70) && (*BColor >= 15) && (*BColor <= 22))
|
||
|
*BColor -= 7;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ReadInDataFileTypeTitleAndVarNames replaces ReadInDataFileTitleAndVarNames
|
||
|
* and reads in the filetype as well in files with version >= 109.
|
||
|
*/
|
||
|
Boolean_t ReadInDataFileTypeTitleAndVarNames(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
char **DataSetTitle,
|
||
|
DataFileType_e *FileType,
|
||
|
int *NumVars,
|
||
|
StringList_pa *VarNames)
|
||
|
{
|
||
|
EntIndex_t CurVar;
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
|
||
|
REQUIRE(VALID_REF(DataSetTitle) || (DataSetTitle == NULL));
|
||
|
REQUIRE(VALID_REF(FileType) || (FileType == NULL));
|
||
|
REQUIRE(VALID_REF(NumVars));
|
||
|
REQUIRE(VALID_REF(VarNames) || (VarNames == NULL));
|
||
|
|
||
|
*NumVars = 0;
|
||
|
if (DataSetTitle)
|
||
|
*DataSetTitle = NULL;
|
||
|
if (IVersion >= 109)
|
||
|
{
|
||
|
if (FileType)
|
||
|
*FileType = (DataFileType_e)GetIoFileInt(FileStream,
|
||
|
IVersion,
|
||
|
0,
|
||
|
DataFileType_Solution,
|
||
|
&IsOk);
|
||
|
else
|
||
|
GetIoFileInt(FileStream,
|
||
|
IVersion,
|
||
|
0,
|
||
|
DataFileType_Solution,
|
||
|
&IsOk);
|
||
|
}
|
||
|
if (ReadInString(FileStream,
|
||
|
IVersion,
|
||
|
((IVersion < 63) ? 80 : MaxChrsDatasetTitle),
|
||
|
DataSetTitle,
|
||
|
(Boolean_t)(DataSetTitle != NULL)))
|
||
|
{
|
||
|
if (DataSetTitle)
|
||
|
TrimLeadAndTrailSpaces(*DataSetTitle);
|
||
|
*NumVars = GetIoFileInt(FileStream, IVersion, 0, MAXZONEMAP, &IsOk);
|
||
|
}
|
||
|
else
|
||
|
IsOk = FALSE;
|
||
|
|
||
|
if (IsOk && (*NumVars > MaxNumZonesOrVars))
|
||
|
{
|
||
|
ErrMsg(translate("Too many variables"));
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
|
||
|
if (IsOk && VarNames)
|
||
|
{
|
||
|
if (*NumVars > 0)
|
||
|
{
|
||
|
/* allocate a string list filled with NULL's */
|
||
|
*VarNames = StringListAlloc();
|
||
|
IsOk = (*VarNames != NULL);
|
||
|
if (IsOk)
|
||
|
IsOk = StringListSetString(*VarNames, *NumVars - 1, NULL);
|
||
|
|
||
|
if (!IsOk)
|
||
|
{
|
||
|
if (*VarNames != NULL)
|
||
|
StringListDealloc(VarNames);
|
||
|
ErrMsg(translate("Out of space while allocating var names"));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (CurVar = 0; IsOk && (CurVar < *NumVars); CurVar++)
|
||
|
{
|
||
|
char *VName = NULL;
|
||
|
|
||
|
IsOk = ReadInString(FileStream,
|
||
|
IVersion,
|
||
|
((IVersion < 63) ? 5 : MaxChrsVarName),
|
||
|
VarNames ? &VName : NULL,
|
||
|
(Boolean_t)(VarNames != NULL));
|
||
|
if (IsOk && VarNames)
|
||
|
{
|
||
|
if (VName == NULL)
|
||
|
{
|
||
|
/* NULL variable names are converted to empty names */
|
||
|
VName = ALLOC_ARRAY(1, char, "empty variable name");
|
||
|
strcpy(VName, "");
|
||
|
}
|
||
|
TrimLeadAndTrailSpaces(VName);
|
||
|
|
||
|
/*
|
||
|
* variables are not allowed to have litteral new line characters
|
||
|
* within them but they can sneek in from ASCII data files so
|
||
|
* convert any to their appropriate two character representation
|
||
|
*/
|
||
|
IsOk = ReplaceNewlineWithBackslashN(&VName);
|
||
|
|
||
|
IsOk = IsOk && StringListSetString(*VarNames, CurVar, VName);
|
||
|
if (VName != NULL)
|
||
|
FREE_ARRAY(VName, "variable name");
|
||
|
}
|
||
|
|
||
|
if (!IsOk)
|
||
|
{
|
||
|
if (VarNames && *VarNames)
|
||
|
StringListDealloc(VarNames);
|
||
|
ErrMsg(translate("Out of space while allocating variable names"));
|
||
|
}
|
||
|
}
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return (IsOk);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
static Boolean_t ReadInPresetZoneColor(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
ZoneSpec_s *ZoneSpec)
|
||
|
{
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
LgIndex_t ZoneColor;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
|
||
|
REQUIRE(VALID_REF(ZoneSpec));
|
||
|
|
||
|
ZoneColor = GetIoFileInt(FileStream, IVersion, -1, LastBasicColor, &IsOk);
|
||
|
if (IsOk)
|
||
|
{
|
||
|
if (VALID_BASIC_COLOR(ZoneColor))
|
||
|
{
|
||
|
ZoneSpec->ZoneLoadInfo.PresetZoneColor = (EntIndex_t)ZoneColor;
|
||
|
AdjustCustomColor(IVersion, &ZoneSpec->ZoneLoadInfo.PresetZoneColor);
|
||
|
}
|
||
|
else if (ZoneColor != -1)
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
static void ConvertCommonTimeToSolutionTime(ZoneSpec_s *ZoneSpec)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(ZoneSpec));
|
||
|
REQUIRE(ZoneSpec->AuxData == NULL || VALID_REF(ZoneSpec->AuxData));
|
||
|
|
||
|
LgIndex_t ItemIndex;
|
||
|
if (ZoneSpec->AuxData != NULL &&
|
||
|
AuxDataGetItemIndex(ZoneSpec->AuxData, AuxData_Common_Time, &ItemIndex))
|
||
|
{
|
||
|
const char *SameName;
|
||
|
ArbParam_t Value;
|
||
|
AuxDataType_e Type;
|
||
|
Boolean_t Retain;
|
||
|
|
||
|
AuxDataGetItemByIndex(ZoneSpec->AuxData, ItemIndex,
|
||
|
&SameName, &Value, &Type, &Retain);
|
||
|
CHECK(ustrcmp(AuxData_Common_Time, SameName) == 0);
|
||
|
CHECK(Type == AuxDataType_String);
|
||
|
|
||
|
char *EndPtr = NULL;
|
||
|
double SolutionTime = strtod((const char *)Value, &EndPtr);
|
||
|
if (EndPtr != (char *)Value)
|
||
|
{
|
||
|
/* we only allow white space to trail a value */
|
||
|
while (isspace(*EndPtr))
|
||
|
EndPtr++;
|
||
|
}
|
||
|
if (EndPtr != (char *)Value && *EndPtr == '\0')
|
||
|
{
|
||
|
ZoneSpec->SolutionTime = SolutionTime;
|
||
|
ZoneSpec->StrandID = STRAND_ID_PENDING;
|
||
|
AuxDataDeleteItemByIndex(ZoneSpec->AuxData, ItemIndex);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Pass1 for a zone reads in and initializes the zone structures.
|
||
|
* These structures are released later if the user elects to not read them
|
||
|
* in.
|
||
|
*/
|
||
|
Boolean_t ReadInZoneHeader(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
ZoneSpec_s *ZoneSpec,
|
||
|
Set_pa IsVarCellCentered,
|
||
|
EntIndex_t NumVars,
|
||
|
Boolean_t *IsRawFNAvailable,
|
||
|
LgIndex_t *FNNumBndryConns)
|
||
|
{
|
||
|
EntIndex_t Var;
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
LgIndex_t I1;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
|
||
|
REQUIRE(VALID_REF(ZoneSpec));
|
||
|
REQUIRE(IsVarCellCentered == NULL || VALID_REF(IsVarCellCentered));
|
||
|
REQUIRE(NumVars >= 0);
|
||
|
REQUIRE(VALID_REF(IsRawFNAvailable));
|
||
|
REQUIRE(VALID_REF(FNNumBndryConns));
|
||
|
|
||
|
SetZoneSpecDefaults(ZoneSpec);
|
||
|
|
||
|
if (IsVarCellCentered != NULL)
|
||
|
{
|
||
|
/* assign default variable value location: nodal */
|
||
|
ClearSet(IsVarCellCentered);
|
||
|
IsOk = ExpandSet(IsVarCellCentered, NumVars, FALSE);
|
||
|
}
|
||
|
|
||
|
if (IsOk)
|
||
|
IsOk = ReadInString(FileStream, IVersion,
|
||
|
((IVersion < 63) ? 10 : MaxChrsZnTitle),
|
||
|
&ZoneSpec->Name,
|
||
|
TRUE);
|
||
|
|
||
|
if (IsOk && ZoneSpec->Name == NULL)
|
||
|
{
|
||
|
/* NULL zone names are converted to empty names */
|
||
|
ZoneSpec->Name = ALLOC_ARRAY(1, char, "empty zone name");
|
||
|
IsOk = (ZoneSpec->Name != NULL);
|
||
|
if (IsOk)
|
||
|
strcpy(ZoneSpec->Name, "");
|
||
|
}
|
||
|
|
||
|
if (IsOk)
|
||
|
TrimLeadAndTrailSpaces(ZoneSpec->Name);
|
||
|
|
||
|
if (IVersion < 101)
|
||
|
{
|
||
|
Boolean_t IsZoneFinite;
|
||
|
DataFormat_e ZoneDataFormat;
|
||
|
|
||
|
I1 = GetIoFileInt(FileStream, IVersion, 0, 3, &IsOk);
|
||
|
|
||
|
if ((I1 < 0) || (I1 > 3))
|
||
|
{
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
ZoneDataFormat = (DataFormat_e)I1;
|
||
|
|
||
|
IsZoneFinite = (ZoneDataFormat == DataFormat_FEPoint ||
|
||
|
ZoneDataFormat == DataFormat_FEBlock);
|
||
|
|
||
|
ZoneSpec->ZoneLoadInfo.IsInBlockFormat = (ZoneDataFormat == DataFormat_IJKBlock ||
|
||
|
ZoneDataFormat == DataFormat_FEBlock);
|
||
|
|
||
|
if (IVersion > 62)
|
||
|
IsOk = ReadInPresetZoneColor(FileStream, IVersion, ZoneSpec);
|
||
|
|
||
|
if (IVersion < 60)
|
||
|
GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); /* Old ZPlane Value */
|
||
|
|
||
|
if (IsOk)
|
||
|
{
|
||
|
ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
if (IVersion >= 60)
|
||
|
ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
else
|
||
|
ZoneSpec->NumPtsK = 1;
|
||
|
}
|
||
|
|
||
|
if (IsOk)
|
||
|
{
|
||
|
/* If IMax,JMax, & KMax are all zero then this zone was "zombied" by
|
||
|
a partial read to make layout files align. */
|
||
|
|
||
|
if (!((ZoneSpec->NumPtsI == 0) &&
|
||
|
(ZoneSpec->NumPtsJ == 0) &&
|
||
|
(ZoneSpec->NumPtsK == 0)) &&
|
||
|
((ZoneSpec->NumPtsI <= 0) ||
|
||
|
(ZoneSpec->NumPtsJ <= 0) ||
|
||
|
(ZoneSpec->NumPtsK < 0) ||
|
||
|
((!IsZoneFinite && (ZoneSpec->NumPtsK == 0)))))
|
||
|
{
|
||
|
ErrMsg(translate("Datafile is corrupted"));
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
|
||
|
if (IsZoneFinite)
|
||
|
{
|
||
|
if (IVersion >= 61)
|
||
|
{
|
||
|
ZoneSpec->Type = (ZoneType_e)(ZoneSpec->NumPtsK + 1);
|
||
|
switch (ZoneSpec->Type)
|
||
|
{
|
||
|
case ZoneType_FETriangle: ZoneSpec->NumPtsK = 3; break;
|
||
|
case ZoneType_FEQuad: ZoneSpec->NumPtsK = 4; break;
|
||
|
case ZoneType_FETetra: ZoneSpec->NumPtsK = 4; break;
|
||
|
case ZoneType_FEBrick: ZoneSpec->NumPtsK = 8; break;
|
||
|
case ZoneType_FELineSeg: ZoneSpec->NumPtsK = 2; break;
|
||
|
default:
|
||
|
{
|
||
|
ErrMsg(translate("Datafile corrupted: Invalid element type for FE DataSet"));
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ZoneSpec->Type = ZoneType_FEQuad;
|
||
|
ZoneSpec->NumPtsK = 4;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ZoneSpec->Type = ZoneType_Ordered;
|
||
|
|
||
|
ZoneSpec->ICellDim = ZoneSpec->NumPtsI - 1;
|
||
|
ZoneSpec->JCellDim = ZoneSpec->NumPtsJ - 1;
|
||
|
ZoneSpec->KCellDim = ZoneSpec->NumPtsK - 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Raw and user defined boundary face neighbors connections were not in
|
||
|
* this or previous versions of the binary data files.
|
||
|
*/
|
||
|
*IsRawFNAvailable = FALSE;
|
||
|
*FNNumBndryConns = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (IsOk && (IVersion >= 107))
|
||
|
{
|
||
|
ZoneSpec->ParentZone = GetIoFileInt(FileStream, IVersion, -1, MAXZONEMAP - 1, &IsOk);
|
||
|
if (!IsOk)
|
||
|
ErrMsg(translate("Invalid datafile: parent zone assignment must be to an existing zone within the same datafile."));
|
||
|
}
|
||
|
|
||
|
if (IsOk && (IVersion >= 106))
|
||
|
{
|
||
|
/* Strand ID and solution time. Strand ID's of STRAND_ID_PENDING, -2, instruct Tecplot to generate strand ID's */
|
||
|
ZoneSpec->StrandID = GetIoFileInt(FileStream, IVersion, -2, MAXZONEMAP - 1, &IsOk);
|
||
|
ZoneSpec->SolutionTime = GetNextValue(FileStream, FieldDataType_Double, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
if (!IsOk)
|
||
|
ErrMsg(translate("Invalid datafile: bad StrandID or SolutionTime"));
|
||
|
}
|
||
|
|
||
|
/* preset zone color */
|
||
|
IsOk = IsOk && ReadInPresetZoneColor(FileStream, IVersion, ZoneSpec);
|
||
|
|
||
|
/* ZoneType */
|
||
|
I1 = (ZoneType_e)GetIoFileInt(FileStream, IVersion, 0, 7, &IsOk);
|
||
|
switch (I1)
|
||
|
{
|
||
|
case 0: ZoneSpec->Type = ZoneType_Ordered; break;
|
||
|
case 1: ZoneSpec->Type = ZoneType_FELineSeg; break;
|
||
|
case 2: ZoneSpec->Type = ZoneType_FETriangle; break;
|
||
|
case 3: ZoneSpec->Type = ZoneType_FEQuad; break;
|
||
|
case 4: ZoneSpec->Type = ZoneType_FETetra; break;
|
||
|
case 5: ZoneSpec->Type = ZoneType_FEBrick; break;
|
||
|
case 6: ZoneSpec->Type = ZoneType_FEPolygon; break;
|
||
|
case 7: ZoneSpec->Type = ZoneType_FEPolyhedron; break;
|
||
|
default:
|
||
|
{
|
||
|
ErrMsg(translate("Invalid datafile: unknown zone type."));
|
||
|
IsOk = FALSE;
|
||
|
} break;
|
||
|
}
|
||
|
|
||
|
/* DataPacking (Always BLOCK starting with file version 112 so removed from binary format) */
|
||
|
if (IVersion < 112)
|
||
|
ZoneSpec->ZoneLoadInfo.IsInBlockFormat =
|
||
|
((DataPacking_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) == DataPacking_Block);
|
||
|
else
|
||
|
ZoneSpec->ZoneLoadInfo.IsInBlockFormat = TRUE;
|
||
|
|
||
|
/* is the variable value location specified? */
|
||
|
if ((Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) && IsOk)
|
||
|
{
|
||
|
/* Variable Value Location foreach Var */
|
||
|
for (Var = 0; Var < NumVars && IsOk; Var++)
|
||
|
{
|
||
|
if ((Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) && IsOk &&
|
||
|
IsVarCellCentered != NULL)
|
||
|
{
|
||
|
IsOk = (ZoneSpec->ZoneLoadInfo.IsInBlockFormat);
|
||
|
if (IsOk)
|
||
|
IsOk = AddToSet(IsVarCellCentered, Var, FALSE);
|
||
|
else
|
||
|
ErrMsg(translate("Invalid datafile: cell centered "
|
||
|
"variable must be in block format.",
|
||
|
"See the Tecplot User's Manual for a definition of 'block format'"));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* are raw face neighbors supplied in the data section? */
|
||
|
if (IVersion >= 108 && IsOk)
|
||
|
{
|
||
|
*IsRawFNAvailable = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
|
||
|
if (*IsRawFNAvailable &&
|
||
|
(ZoneSpec->Type == ZoneType_Ordered ||
|
||
|
ZoneSpec->Type == ZoneType_FELineSeg))
|
||
|
{
|
||
|
IsOk = FALSE;
|
||
|
ErrMsg(translate("Invalid datafile: raw face neighbors may not be "
|
||
|
"supplied for ordered or FE line segment zones."));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
*IsRawFNAvailable = FALSE;
|
||
|
|
||
|
/*
|
||
|
* If raw face neighbors are available in the datafile then Tecplot
|
||
|
* should not auto-assign the neighbors after the load.
|
||
|
*/
|
||
|
ZoneSpec->FNAreCellFaceNbrsSupplied = *IsRawFNAvailable;
|
||
|
|
||
|
/* miscellaneous face neighbor info */
|
||
|
*FNNumBndryConns = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
if (*FNNumBndryConns != 0)
|
||
|
ZoneSpec->FNMode = (FaceNeighborMode_e)GetIoFileInt(FileStream, IVersion, 0, 3, &IsOk);
|
||
|
|
||
|
if (IVersion >= 108 && IsOk)
|
||
|
{
|
||
|
Boolean_t FaceNeighborsComplete = FALSE;
|
||
|
if (*FNNumBndryConns != 0 &&
|
||
|
ZoneSpec->Type != ZoneType_Ordered)
|
||
|
FaceNeighborsComplete = (Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
|
||
|
|
||
|
/*
|
||
|
* If the user defined face neighbors completely specify all the
|
||
|
* face neighbors then we don't want to auto-assign the cell face
|
||
|
* neighbors after loading. If they are not complete then leave the
|
||
|
* setting (as set above) dependent on the availability of the raw
|
||
|
* face neighbors.
|
||
|
*
|
||
|
* NOTE:
|
||
|
* This is a rather inefficient way to specify face neighbors.
|
||
|
*/
|
||
|
if (FaceNeighborsComplete)
|
||
|
ZoneSpec->FNAreCellFaceNbrsSupplied = TRUE;
|
||
|
}
|
||
|
|
||
|
if (ZoneSpec->Type == ZoneType_Ordered)
|
||
|
{
|
||
|
/* IMax, JMax, KMax */
|
||
|
ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
/*
|
||
|
* if not a zombie zone (zombie zone: points in all dimensions are
|
||
|
* zero) then points in each direction must be specified
|
||
|
*/
|
||
|
if (IsOk &&
|
||
|
!(ZoneSpec->NumPtsI == 0 &&
|
||
|
ZoneSpec->NumPtsJ == 0 &&
|
||
|
ZoneSpec->NumPtsK == 0) &&
|
||
|
(ZoneSpec->NumPtsI == 0 ||
|
||
|
ZoneSpec->NumPtsJ == 0 ||
|
||
|
ZoneSpec->NumPtsK == 0))
|
||
|
{
|
||
|
ErrMsg(translate("Invalid data file: incorrect specification of "
|
||
|
"I, J, or K points for ordered data set."));
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
if (ZoneSpec->Type == ZoneType_FEPolygon || ZoneSpec->Type == ZoneType_FEPolyhedron)
|
||
|
{
|
||
|
ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); // ...NumFaces
|
||
|
if (IVersion >= 111)
|
||
|
{
|
||
|
ZoneSpec->NumFaceNodes = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
ZoneSpec->NumFaceBndryFaces = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
ZoneSpec->NumFaceBndryItems = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
switch (ZoneSpec->Type)
|
||
|
{
|
||
|
case ZoneType_FETriangle: ZoneSpec->NumPtsK = 3; break;
|
||
|
case ZoneType_FEQuad: ZoneSpec->NumPtsK = 4; break;
|
||
|
case ZoneType_FETetra: ZoneSpec->NumPtsK = 4; break;
|
||
|
case ZoneType_FEBrick: ZoneSpec->NumPtsK = 8; break;
|
||
|
case ZoneType_FELineSeg: ZoneSpec->NumPtsK = 2; break;
|
||
|
default :
|
||
|
{
|
||
|
ErrMsg(translate("Invalid data file: invalid element type for FE data set."));
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
|
||
|
ZoneSpec->ICellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
ZoneSpec->JCellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
ZoneSpec->KCellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
|
||
|
}
|
||
|
|
||
|
/* Zone Auxiliary Data indicator followed by Zone Auxiliary Data */
|
||
|
for (I1 = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
|
||
|
IsOk && I1 != 0;
|
||
|
I1 = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk))
|
||
|
{
|
||
|
if (ZoneSpec->AuxData == NULL)
|
||
|
ZoneSpec->AuxData = AuxDataAlloc();
|
||
|
IsOk = (ZoneSpec->AuxData != NULL);
|
||
|
if (IsOk)
|
||
|
IsOk = ReadInAuxData(FileStream, IVersion, ZoneSpec->AuxData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Convert AuxZone's Common.Time from non-time aware data files to zone
|
||
|
* solution time if it exists.
|
||
|
*/
|
||
|
if (IVersion < 106 && IsOk)
|
||
|
ConvertCommonTimeToSolutionTime(ZoneSpec);
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return (IsOk);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Pass1 for Custom labels simply acknowledges that a custom label was
|
||
|
* parsed and skips over the labels.
|
||
|
*/
|
||
|
|
||
|
Boolean_t ReadInCustomLabels(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
Boolean_t OkToLoad,
|
||
|
StringList_pa *CustomLabelBase)
|
||
|
{
|
||
|
LgIndex_t NumLabels;
|
||
|
short I;
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(IVersion > 0);
|
||
|
REQUIRE(VALID_BOOLEAN(OkToLoad));
|
||
|
REQUIRE(!(OkToLoad) || VALID_REF(CustomLabelBase));
|
||
|
|
||
|
NumLabels = (short)GetIoFileInt(FileStream, IVersion, 1, MAXINDEX, &IsOk);
|
||
|
if (IsOk && NumLabels != 0 && OkToLoad)
|
||
|
{
|
||
|
*CustomLabelBase = StringListAlloc();
|
||
|
IsOk = (*CustomLabelBase != NULL);
|
||
|
if (!IsOk)
|
||
|
ErrMsg(translate("Cannot allocate memory for Custom Labels."));
|
||
|
}
|
||
|
|
||
|
for (I = 0; IsOk && (I < NumLabels); I++)
|
||
|
{
|
||
|
char *TLabel = NULL;
|
||
|
|
||
|
IsOk = ReadInString(FileStream, IVersion,
|
||
|
1024,
|
||
|
&TLabel,
|
||
|
OkToLoad);
|
||
|
TrimLeadAndTrailSpaces(TLabel);
|
||
|
|
||
|
if (IsOk && OkToLoad)
|
||
|
{
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
IsOk = StringListAppendString(*CustomLabelBase, TLabel);
|
||
|
if (TLabel != NULL)
|
||
|
FREE_ARRAY(TLabel, "custom label");
|
||
|
if (!IsOk)
|
||
|
ErrMsg(translate("Cannot allocate memory for Custom Label."));
|
||
|
}
|
||
|
}
|
||
|
if (!IsOk)
|
||
|
ErrMsg(translate("Invalid custom axis label record in binary datafile"));
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
ENSURE(!(IsOk && NumLabels != 0 && OkToLoad) ||
|
||
|
StringListValid(*CustomLabelBase));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
Boolean_t ReadInUserRec(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
int MaxCharactersAllowed,
|
||
|
char **UserRec) /* NULL if to ignore */
|
||
|
{
|
||
|
if (!ReadInString(FileStream, IVersion,
|
||
|
MaxCharactersAllowed,
|
||
|
UserRec,
|
||
|
(Boolean_t)(UserRec != NULL)))
|
||
|
{
|
||
|
ErrMsg(translate("Invalid USERREC record in binary datafile"));
|
||
|
return (FALSE);
|
||
|
}
|
||
|
return (TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
Boolean_t ReadInAuxData(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
AuxData_pa AuxData)
|
||
|
{
|
||
|
Boolean_t IsOk;
|
||
|
Boolean_t DoCollectData;
|
||
|
char *AuxName = NULL;
|
||
|
LgIndex_t AuxValueType;
|
||
|
char *AuxValue = NULL;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
|
||
|
REQUIRE(AuxData == NULL || VALID_REF(AuxData));
|
||
|
|
||
|
DoCollectData = (AuxData != NULL);
|
||
|
IsOk = ReadInString(FileStream,
|
||
|
IVersion,
|
||
|
MaxChrsVarName, /* ... seems reasonable */
|
||
|
&AuxName,
|
||
|
DoCollectData);
|
||
|
if (IsOk && DoCollectData && !AuxDataIsValidName(AuxName))
|
||
|
{
|
||
|
ErrMsg(translate("Invalid auxiliary data name."));
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* currently only one value type is supported
|
||
|
* 0: AuxiliaryValueFormat_String
|
||
|
*/
|
||
|
if (IsOk)
|
||
|
{
|
||
|
AuxValueType = GetIoFileInt(FileStream, IVersion, 0, 0, &IsOk);
|
||
|
if (IsOk && (AuxValueType != (LgIndex_t)AuxDataType_String))
|
||
|
{
|
||
|
ErrMsg(translate("Unsupported auxiliary data type"));
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (IsOk)
|
||
|
IsOk = ReadInString(FileStream,
|
||
|
IVersion,
|
||
|
MaxChrsAuxValueString,
|
||
|
&AuxValue,
|
||
|
DoCollectData);
|
||
|
if (IsOk && DoCollectData)
|
||
|
IsOk = AuxDataSetItem(AuxData,
|
||
|
AuxName, (ArbParam_t)AuxValue,
|
||
|
AuxDataType_String,
|
||
|
TRUE); /* Retain */
|
||
|
|
||
|
/* cleanup: auxiliary data made a copy of the name and value */
|
||
|
if (AuxName != NULL)
|
||
|
FREE_ARRAY(AuxName, "data set auxiliary data item name");
|
||
|
if (AuxValue != NULL)
|
||
|
FREE_ARRAY(AuxValue, "data set auxiliary data item value");
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
static void GetZoneAttachment(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
EntIndex_t *Z,
|
||
|
Boolean_t *IsAttached,
|
||
|
Boolean_t *IsOk)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(VALID_REF(Z));
|
||
|
REQUIRE(VALID_REF(IsAttached));
|
||
|
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
|
||
|
|
||
|
if (IVersion >= 47)
|
||
|
*Z = (EntIndex_t)GetIoFileInt(FileStream, IVersion, -1, MAXZONEMAP, IsOk);
|
||
|
else
|
||
|
*Z = 0;
|
||
|
|
||
|
if (IVersion < 70)
|
||
|
(*Z)--;
|
||
|
|
||
|
if (*Z == -1)
|
||
|
{
|
||
|
*Z = 0;
|
||
|
*IsAttached = FALSE;
|
||
|
}
|
||
|
else
|
||
|
*IsAttached = TRUE;
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(*IsAttached));
|
||
|
ENSURE(VALID_BOOLEAN(*IsOk));
|
||
|
ENSURE(*Z >= 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
static Boolean_t ReadMacroFunctionCommand(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
Boolean_t OkToLoad,
|
||
|
char **MacroFunctionCommand)
|
||
|
{
|
||
|
Boolean_t Result = FALSE;
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(IVersion > 0);
|
||
|
REQUIRE(VALID_BOOLEAN(OkToLoad));
|
||
|
REQUIRE(VALID_REF(MacroFunctionCommand));
|
||
|
|
||
|
Result = ReadInString(FileStream, IVersion, 0, MacroFunctionCommand, OkToLoad);
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(Result));
|
||
|
return (Result);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Pass1 for Geometries simply acknowledges that a geometry was
|
||
|
* parsed and skips over the geometry.
|
||
|
*/
|
||
|
Boolean_t ReadInGeometry(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
Boolean_t OkToLoad,
|
||
|
Geom_s *Geom,
|
||
|
LgIndex_t MaxDataPts)
|
||
|
{
|
||
|
LgIndex_t I;
|
||
|
LgIndex_t S;
|
||
|
FieldDataType_e FFT;
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
TranslatedString ErrMsgString = translate("Invalid geometry record");
|
||
|
|
||
|
REQUIRE(VALID_REF(Geom));
|
||
|
|
||
|
if (IVersion < 70)
|
||
|
FFT = FieldDataType_Float;
|
||
|
else
|
||
|
FFT = FieldDataType_Double;
|
||
|
|
||
|
if (IVersion < 101)
|
||
|
I = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
|
||
|
else
|
||
|
I = GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk);
|
||
|
|
||
|
if (I == 0)
|
||
|
Geom->PositionCoordSys = CoordSys_Grid;
|
||
|
else if (I == 1)
|
||
|
Geom->PositionCoordSys = CoordSys_Frame;
|
||
|
/*
|
||
|
* I == 2 is for CoordSys_FrameOffset and is not used currently
|
||
|
*
|
||
|
* I == 3 is for the old window coordinate system
|
||
|
*/
|
||
|
else if (I == 4)
|
||
|
Geom->PositionCoordSys = CoordSys_Grid3D;
|
||
|
else
|
||
|
{
|
||
|
ErrMsgString = translate("Invalid geometry coordinate system");
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
|
||
|
Geom->Scope = (Scope_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
|
||
|
if (IVersion >= 102)
|
||
|
Geom->DrawOrder = (DrawOrder_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
|
||
|
Geom->AnchorPos.Generic.V1 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
Geom->AnchorPos.Generic.V2 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
if (IVersion >= 45)
|
||
|
Geom->AnchorPos.Generic.V3 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
else
|
||
|
Geom->AnchorPos.Generic.V3 = 0.0;
|
||
|
|
||
|
GetZoneAttachment(FileStream, IVersion, &Geom->Zone, &Geom->AttachToZone, &IsOk);
|
||
|
|
||
|
Geom->BColor = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
|
||
|
|
||
|
AdjustCustomColor(IVersion, &Geom->BColor);
|
||
|
|
||
|
if (IVersion > 47)
|
||
|
{
|
||
|
Geom->FillBColor = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
|
||
|
Geom->IsFilled = (Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
|
||
|
AdjustCustomColor(IVersion, &Geom->FillBColor);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Geom->FillBColor = Geom->BColor;
|
||
|
Geom->IsFilled = FALSE;
|
||
|
}
|
||
|
|
||
|
if (IVersion < 101)
|
||
|
{
|
||
|
Geom->GeomType = (GeomType_e)GetIoFileInt(FileStream, IVersion, 0, 5, &IsOk);
|
||
|
if (Geom->GeomType == GeomType_LineSegs3D)
|
||
|
{
|
||
|
/*
|
||
|
* GeomType_LineSegs3D is deprecated, converter to GeomType_LineSegs
|
||
|
* with CoordSys_Grid3D instead
|
||
|
*/
|
||
|
Geom->GeomType = GeomType_LineSegs;
|
||
|
Geom->PositionCoordSys = CoordSys_Grid3D; /*...should have been anyway */
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Geom->GeomType = (GeomType_e)GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Check geom coord sys versus geom type
|
||
|
*/
|
||
|
if (Geom->PositionCoordSys == CoordSys_Grid3D &&
|
||
|
Geom->GeomType != GeomType_LineSegs)
|
||
|
{
|
||
|
ErrMsgString = translate("Mismatch between geometry coordinate system and geometry type");
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
|
||
|
if (IVersion > 41)
|
||
|
{
|
||
|
Geom->LinePattern = (LinePattern_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)LinePattern_DashDotDot, &IsOk);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Geom->LinePattern = (LinePattern_e)((int)Geom->GeomType % 2);
|
||
|
Geom->GeomType = (GeomType_e)((int)Geom->GeomType / 10);
|
||
|
}
|
||
|
|
||
|
if ((IVersion < 49) && ((short)(Geom->GeomType) == 2))
|
||
|
{
|
||
|
Geom->GeomType = GeomType_Rectangle;
|
||
|
Geom->IsFilled = TRUE;
|
||
|
}
|
||
|
|
||
|
if ((IVersion < 70) && ((short)(Geom->GeomType) > 1))
|
||
|
Geom->GeomType = (GeomType_e)((short)Geom->GeomType + 1);
|
||
|
|
||
|
ResetString(&Geom->MacroFunctionCommand, NULL, TRUE);
|
||
|
|
||
|
Geom->ImageResizeFilter = ImageResizeFilter_Texture;
|
||
|
|
||
|
if (IVersion >= 70)
|
||
|
{
|
||
|
Geom->PatternLength = GetNextValue(FileStream, FFT,
|
||
|
PatternLengthInputSpec.Min,
|
||
|
PatternLengthInputSpec.Max,
|
||
|
&IsOk);
|
||
|
Geom->LineThickness = GetNextValue(FileStream, FFT,
|
||
|
LineThicknessInputSpec.Min,
|
||
|
LineThicknessInputSpec.Max,
|
||
|
&IsOk);
|
||
|
Geom->NumEllipsePts = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 2, MaxPtsCircleOrEllipse, &IsOk);
|
||
|
Geom->ArrowheadStyle = (ArrowheadStyle_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)ArrowheadStyle_Hollow, &IsOk);
|
||
|
Geom->ArrowheadAttachment = (ArrowheadAttachment_e)GetIoFileInt(FileStream, IVersion,
|
||
|
0,
|
||
|
(LgIndex_t)ArrowheadAttachment_AtBothEnds,
|
||
|
&IsOk);
|
||
|
|
||
|
Geom->ArrowheadSize = GetNextValue(FileStream, FFT,
|
||
|
ArrowheadSizeInputSpec.Min,
|
||
|
ArrowheadSizeInputSpec.Max,
|
||
|
&IsOk);
|
||
|
Geom->ArrowheadAngle = GetNextValue(FileStream, FFT,
|
||
|
ArrowheadAngleInputSpec.Min,
|
||
|
ArrowheadAngleInputSpec.Max,
|
||
|
&IsOk);
|
||
|
|
||
|
if (IVersion >= 75)
|
||
|
{
|
||
|
IsOk = ReadMacroFunctionCommand(FileStream,
|
||
|
IVersion,
|
||
|
OkToLoad,
|
||
|
&Geom->MacroFunctionCommand);
|
||
|
} /* version >= 75 */
|
||
|
} /* version >= 70 */
|
||
|
else
|
||
|
{
|
||
|
Geom->LineThickness = 0.001;
|
||
|
Geom->PatternLength = 0.02;
|
||
|
Geom->ArrowheadStyle = ArrowheadStyle_Plain;
|
||
|
Geom->ArrowheadAttachment = ArrowheadAttachment_None;
|
||
|
Geom->ArrowheadSize = 0.05;
|
||
|
Geom->ArrowheadAngle = 12.0 / DEGPERRADIANS;
|
||
|
}
|
||
|
|
||
|
if (IVersion < 41)
|
||
|
{
|
||
|
GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
}
|
||
|
|
||
|
if (IVersion < 70)
|
||
|
Geom->DataType = FieldDataType_Float;
|
||
|
else
|
||
|
Geom->DataType = (FieldDataType_e)GetIoFileInt(FileStream, IVersion, 1, 2, &IsOk);
|
||
|
CHECK(VALID_GEOM_FIELD_DATA_TYPE(Geom->DataType));
|
||
|
|
||
|
Geom->Clipping = Clipping_ClipToViewport; /* default value for pre 101 versions */
|
||
|
if (IVersion >= 101)
|
||
|
{
|
||
|
Geom->Clipping = (Clipping_e)GetIoFileInt(FileStream, IVersion, 0, 2, &IsOk);
|
||
|
/*
|
||
|
* The second clipping value was deprecated during v10 development and thus removed.
|
||
|
* This moved Clipping_ClipToFrame to the 2nd position from the 3rd, so we convert
|
||
|
* value 2 to ClipToFrame to support files made during v10 developement.
|
||
|
*/
|
||
|
if (Geom->Clipping == (Clipping_e)2)
|
||
|
Geom->Clipping = Clipping_ClipToFrame;
|
||
|
}
|
||
|
|
||
|
if (IVersion < 50 ||
|
||
|
Geom->GeomType == GeomType_LineSegs)
|
||
|
{
|
||
|
Geom->NumSegments = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 1, MaxGeoSegments, &IsOk);
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
S = -1;
|
||
|
I = 0;
|
||
|
while ((S + 1 < Geom->NumSegments) &&
|
||
|
!feof(FileStream->File) && IsOk)
|
||
|
{
|
||
|
S++;
|
||
|
Geom->NumSegPts[S] = GetIoFileInt(FileStream, IVersion, 1, MAXINDEX, &IsOk);
|
||
|
if ((I + Geom->NumSegPts[S] > MaxDataPts) && OkToLoad)
|
||
|
{
|
||
|
ErrMsgString = translate("Geometry is too big");
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ReadBlock(FileStream, Geom->GeomData.Generic.V1Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk);
|
||
|
ReadBlock(FileStream, Geom->GeomData.Generic.V2Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk);
|
||
|
if (Geom->PositionCoordSys == CoordSys_Grid3D)
|
||
|
ReadBlock(FileStream, Geom->GeomData.Generic.V3Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk);
|
||
|
I += Geom->NumSegPts[S];
|
||
|
}
|
||
|
}
|
||
|
if (IsOk && (Geom->GeomType == GeomType_Rectangle)) /* IVersion < 50 */
|
||
|
{
|
||
|
if (OkToLoad)
|
||
|
{
|
||
|
CopyFieldValue(Geom->GeomData.Generic.V1Base, 0, Geom->GeomData.Generic.V1Base, 2);
|
||
|
CopyFieldValue(Geom->GeomData.Generic.V2Base, 0, Geom->GeomData.Generic.V2Base, 2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (Geom->GeomType == GeomType_Rectangle ||
|
||
|
Geom->GeomType == GeomType_Ellipse)
|
||
|
{
|
||
|
double XX, YY;
|
||
|
XX = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
YY = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
if (OkToLoad)
|
||
|
{
|
||
|
SetFieldValue(Geom->GeomData.XYZ.XBase, 0, XX);
|
||
|
SetFieldValue(Geom->GeomData.XYZ.YBase, 0, YY);
|
||
|
}
|
||
|
Geom->NumSegments = 1;
|
||
|
Geom->NumSegPts[0] = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
double XX;
|
||
|
CHECK((Geom->GeomType == GeomType_Square) ||
|
||
|
(Geom->GeomType == GeomType_Circle));
|
||
|
XX = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
if (OkToLoad)
|
||
|
{
|
||
|
SetFieldValue(Geom->GeomData.XYZ.XBase, 0, XX);
|
||
|
}
|
||
|
Geom->NumSegments = 1;
|
||
|
Geom->NumSegPts[0] = 1;
|
||
|
}
|
||
|
|
||
|
if (!IsOk)
|
||
|
ErrMsg(ErrMsgString);
|
||
|
|
||
|
return (IsOk);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Pass1 for text simply acknowledges that a text was
|
||
|
* parsed and skips over the text.
|
||
|
*/
|
||
|
Boolean_t ReadInText(FileStream_s *FileStream,
|
||
|
short IVersion,
|
||
|
Boolean_t OkToLoad,
|
||
|
Text_s *Text,
|
||
|
LgIndex_t MaxTextLen)
|
||
|
{
|
||
|
LgIndex_t I;
|
||
|
FieldDataType_e FFT;
|
||
|
SmInteger_t TextLength = 0;
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
TranslatedString ErrMsgString = translate("Invalid text record");
|
||
|
|
||
|
REQUIRE(VALID_REF(Text));
|
||
|
|
||
|
if (IVersion < 70)
|
||
|
FFT = FieldDataType_Float;
|
||
|
else
|
||
|
FFT = FieldDataType_Double;
|
||
|
|
||
|
if (IVersion < 101)
|
||
|
I = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
|
||
|
else
|
||
|
I = GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk);
|
||
|
|
||
|
if (I == 0)
|
||
|
Text->PositionCoordSys = CoordSys_Grid;
|
||
|
else if (I == 1)
|
||
|
Text->PositionCoordSys = CoordSys_Frame;
|
||
|
/*
|
||
|
* I == 2 is for CoordSys_FrameOffset and is not used currently
|
||
|
*
|
||
|
* I == 3 is for the old window coordinate system
|
||
|
*/
|
||
|
else if (I == 4)
|
||
|
Text->PositionCoordSys = CoordSys_Grid3D;
|
||
|
else
|
||
|
{
|
||
|
ErrMsgString = translate("Invalid text coordinate system.");
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
|
||
|
Text->Scope = (Scope_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
|
||
|
Text->AnchorPos.Generic.V1 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
Text->AnchorPos.Generic.V2 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
if (IVersion >= 101)
|
||
|
Text->AnchorPos.Generic.V3 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
else
|
||
|
Text->AnchorPos.Generic.V3 = 0.0; /* default value for pre 101 versions */
|
||
|
|
||
|
if (IVersion > 40)
|
||
|
Text->TextShape.Font = (Font_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)Font_CourierBold, &IsOk);
|
||
|
else
|
||
|
Text->TextShape.Font = Font_Helvetica;
|
||
|
if (IVersion < 43)
|
||
|
GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
if (IVersion < 70)
|
||
|
{
|
||
|
if (Text->PositionCoordSys == CoordSys_Grid)
|
||
|
Text->TextShape.SizeUnits = Units_Grid;
|
||
|
else
|
||
|
Text->TextShape.SizeUnits = Units_Frame;
|
||
|
}
|
||
|
else
|
||
|
Text->TextShape.SizeUnits = (Units_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)Units_Point, &IsOk);
|
||
|
|
||
|
Text->TextShape.Height = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
|
||
|
if (IVersion > 47)
|
||
|
{
|
||
|
Text->Box.BoxType = (TextBox_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)TextBox_Hollow, &IsOk);
|
||
|
if (IVersion < 70)
|
||
|
{
|
||
|
if (Text->Box.BoxType == TextBox_Hollow)
|
||
|
Text->Box.BoxType = TextBox_Filled;
|
||
|
else if (Text->Box.BoxType == TextBox_Filled)
|
||
|
Text->Box.BoxType = TextBox_Hollow;
|
||
|
}
|
||
|
Text->Box.Margin = GetNextValue(FileStream, FFT,
|
||
|
TextBoxMarginInputSpec.Min,
|
||
|
TextBoxMarginInputSpec.Max,
|
||
|
&IsOk);
|
||
|
if (IVersion >= 70)
|
||
|
Text->Box.LineThickness = GetNextValue(FileStream, FFT,
|
||
|
LineThicknessInputSpec.Min,
|
||
|
LineThicknessInputSpec.Max,
|
||
|
&IsOk);
|
||
|
else
|
||
|
Text->Box.LineThickness = 0.01;
|
||
|
Text->Box.BColor = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
|
||
|
Text->Box.FillBColor = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
|
||
|
AdjustCustomColor(IVersion, &Text->Box.BColor);
|
||
|
AdjustCustomColor(IVersion, &Text->Box.FillBColor);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Text->Box.BoxType = TextBox_None;
|
||
|
Text->Box.Margin = 0.0;
|
||
|
Text->Box.BColor = White_C;
|
||
|
Text->Box.FillBColor = Black_C;
|
||
|
}
|
||
|
if (IVersion < 70)
|
||
|
{
|
||
|
Text->Angle = GetIoFileInt(FileStream, IVersion, -720, 720, &IsOk) / DEGPERRADIANS;
|
||
|
Text->LineSpacing = 1;
|
||
|
Text->Anchor = TextAnchor_Left;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Text->Angle = GetNextValue(FileStream, FFT,
|
||
|
TextAngleInputSpec.Min,
|
||
|
TextAngleInputSpec.Max,
|
||
|
&IsOk);
|
||
|
Text->LineSpacing = GetNextValue(FileStream, FFT,
|
||
|
TextLineSpacingInputSpec.Min,
|
||
|
TextLineSpacingInputSpec.Max,
|
||
|
&IsOk);
|
||
|
Text->Anchor = (TextAnchor_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)TextAnchor_HeadRight, &IsOk);
|
||
|
}
|
||
|
|
||
|
GetZoneAttachment(FileStream, IVersion, &Text->Zone, &Text->AttachToZone, &IsOk);
|
||
|
|
||
|
Text->BColor = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
|
||
|
AdjustCustomColor(IVersion, &Text->BColor);
|
||
|
if (IVersion < 70)
|
||
|
TextLength = (short)GetIoFileInt(FileStream, IVersion, 0, 5000, &IsOk);
|
||
|
|
||
|
ResetString(&Text->MacroFunctionCommand, NULL, TRUE);
|
||
|
|
||
|
Text->Clipping = Clipping_ClipToViewport; /* default value for pre 101 versions */
|
||
|
|
||
|
if (IVersion < 70)
|
||
|
{
|
||
|
short I, S;
|
||
|
for (I = 0; I < TextLength; I++)
|
||
|
{
|
||
|
S = (short)GetIoFileInt(FileStream, IVersion, 0, 1000, &IsOk);
|
||
|
if (OkToLoad && (I <= MaxTextLen))
|
||
|
Text->Text[I] = (char)S;
|
||
|
}
|
||
|
if (OkToLoad)
|
||
|
Text->Text[MIN(TextLength, MaxTextLen)] = '\0';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
char *S = NULL;
|
||
|
|
||
|
if (IVersion >= 75)
|
||
|
{
|
||
|
IsOk = ReadMacroFunctionCommand(FileStream,
|
||
|
IVersion,
|
||
|
OkToLoad,
|
||
|
&Text->MacroFunctionCommand);
|
||
|
} /* IVersion >= 75 */
|
||
|
|
||
|
if (IVersion >= 101)
|
||
|
{
|
||
|
/*
|
||
|
* The second clipping value was deprecated during v10 development and thus removed.
|
||
|
* This moved Clipping_ClipToFrame to the 2nd position from the 3rd, so we convert
|
||
|
* value 2 to ClipToFrame to support files made during v10 developement.
|
||
|
*/
|
||
|
Text->Clipping = (Clipping_e)GetIoFileInt(FileStream, IVersion, 0, 2, &IsOk);
|
||
|
if (Text->Clipping == (Clipping_e)2)
|
||
|
Text->Clipping = Clipping_ClipToFrame;
|
||
|
}
|
||
|
|
||
|
if (ReadInString(FileStream,
|
||
|
IVersion,
|
||
|
MaxTextLen,
|
||
|
&S,
|
||
|
OkToLoad))
|
||
|
{
|
||
|
REQUIRE(!(S || OkToLoad) || VALID_REF(Text->Text));
|
||
|
if (S)
|
||
|
{
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif /* TECPLOTKERNEL */
|
||
|
if (IsOk)
|
||
|
{
|
||
|
strcpy(Text->Text, S);
|
||
|
}
|
||
|
FREE_ARRAY(S, "Release temp string for new text label");
|
||
|
}
|
||
|
else if (OkToLoad)
|
||
|
Text->Text[0] = '\0';
|
||
|
}
|
||
|
else
|
||
|
IsOk = FALSE;
|
||
|
}
|
||
|
|
||
|
if (!IsOk)
|
||
|
ErrMsg(ErrMsgString);
|
||
|
|
||
|
return (IsOk);
|
||
|
}
|
||
|
|
||
|
|
||
|
static Boolean_t CompareVersion(float Version,
|
||
|
char *VersionString,
|
||
|
Boolean_t IsByteOrderNative)
|
||
|
{
|
||
|
char *VersionBuf = (char *) & Version;
|
||
|
|
||
|
REQUIRE(VALID_REF(VersionString));
|
||
|
|
||
|
if (IsByteOrderNative)
|
||
|
return ((VersionString[0] == VersionBuf[0]) &&
|
||
|
(VersionString[1] == VersionBuf[1]) &&
|
||
|
(VersionString[2] == VersionBuf[2]) &&
|
||
|
(VersionString[3] == VersionBuf[3]));
|
||
|
else
|
||
|
return ((VersionString[3] == VersionBuf[0]) &&
|
||
|
(VersionString[2] == VersionBuf[1]) &&
|
||
|
(VersionString[1] == VersionBuf[2]) &&
|
||
|
(VersionString[0] == VersionBuf[3]));
|
||
|
}
|
||
|
|
||
|
static float ValidVersions[] = {7.0F,
|
||
|
6.3F, 6.2F, 6.1F, 6.0F,
|
||
|
5.0F,
|
||
|
4.7F, 4.6F, 4.5F, 4.4F, 4.3F, 4.2F, 4.1F, 4.0F
|
||
|
};
|
||
|
#define NUMVALIDVERSIONS ((int)(sizeof(ValidVersions)/sizeof(ValidVersions[0])))
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Extra caution taken here in case value read is invalid float
|
||
|
*/
|
||
|
static Boolean_t GetDoubleVersion(char *VersionString,
|
||
|
float *FInputVersion,
|
||
|
Boolean_t IsByteOrderNative)
|
||
|
{
|
||
|
int I;
|
||
|
REQUIRE(VALID_REF(FInputVersion));
|
||
|
|
||
|
for (I = 0; I < NUMVALIDVERSIONS; I++)
|
||
|
if (CompareVersion(ValidVersions[I], VersionString, IsByteOrderNative))
|
||
|
{
|
||
|
*FInputVersion = ValidVersions[I];
|
||
|
return (TRUE);
|
||
|
}
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
|
||
|
static short GetNewInputVersion(FileStream_s *FileStream)
|
||
|
{
|
||
|
/*
|
||
|
*
|
||
|
*/
|
||
|
char Buf[4];
|
||
|
short IVersion = 0;
|
||
|
short I;
|
||
|
LgIndex_t OneValue;
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(FileStream->IsByteOrderNative);
|
||
|
|
||
|
if (TP_FREAD(Buf, 4, 1, FileStream->File) != 1)
|
||
|
return (0);
|
||
|
|
||
|
if (strncmp(Buf, "#!TD", 4))
|
||
|
return (0);
|
||
|
|
||
|
if (TP_FREAD(Buf, 4, 1, FileStream->File) != 1)
|
||
|
return (0);
|
||
|
|
||
|
if (Buf[0] != 'V')
|
||
|
return (0);
|
||
|
|
||
|
I = 1;
|
||
|
while ((I < 4) && isdigit(Buf[I]))
|
||
|
IVersion = IVersion * 10 + Buf[I++] - '0';
|
||
|
|
||
|
if (IVersion < 70)
|
||
|
return (0);
|
||
|
else if (IVersion > TecplotBinaryFileVersion)
|
||
|
{
|
||
|
ErrMsg(translate("Binary file version newer than Tecplot version. "
|
||
|
"Upgrade Tecplot or use an older Preplot to produce "
|
||
|
"the datafile."));
|
||
|
return (IVersion);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Determine Byte Order.
|
||
|
*/
|
||
|
|
||
|
OneValue = GetIoFileInt(FileStream,
|
||
|
IVersion,
|
||
|
-MAXINDEX,
|
||
|
MAXINDEX,
|
||
|
&IsOk);
|
||
|
|
||
|
if (!IsOk)
|
||
|
return (0);
|
||
|
|
||
|
FileStream->IsByteOrderNative = (OneValue == 1);
|
||
|
|
||
|
return (IVersion);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return value of zero is to be considered as an invalid
|
||
|
* tecplot binary datafile header. Actually binary files
|
||
|
* older than version 4.0 (return value of 40) are not supported
|
||
|
* (See notes in preplot.c).
|
||
|
*/
|
||
|
short GetInputVersion(FileStream_s *FileStream)
|
||
|
{
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
float FInputVersion;
|
||
|
short IVersion;
|
||
|
char VersionString[4];
|
||
|
FileOffset_t StartOffset = 0;
|
||
|
|
||
|
/*
|
||
|
* First check to see if file uses new
|
||
|
* input version format.
|
||
|
*/
|
||
|
|
||
|
/* keep track of our start offset */
|
||
|
StartOffset = TP_FTELL(FileStream->File);
|
||
|
|
||
|
IVersion = GetNewInputVersion(FileStream);
|
||
|
|
||
|
if (IVersion > TecplotBinaryFileVersion)
|
||
|
return IVersion; /* unsupported version */
|
||
|
else if (IVersion == 0)
|
||
|
{
|
||
|
/* rewind to clear any errors and seek to the start offset */
|
||
|
rewind(FileStream->File);
|
||
|
IsOk = (TP_FSEEK(FileStream->File, StartOffset, SEEK_SET) == 0);
|
||
|
|
||
|
if (IsOk && TP_FREAD(VersionString, 4, 1, FileStream->File) == 1)
|
||
|
{
|
||
|
/* try both native and foreign versions numbers */
|
||
|
if (!GetDoubleVersion(VersionString, &FInputVersion, FileStream->IsByteOrderNative))
|
||
|
{
|
||
|
FileStream->IsByteOrderNative = !FileStream->IsByteOrderNative; /* ...reverse the byte order */
|
||
|
IsOk = GetDoubleVersion(VersionString, &FInputVersion, FileStream->IsByteOrderNative);
|
||
|
}
|
||
|
if (IsOk)
|
||
|
IVersion = ROUNDS(FInputVersion * 10);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (IsOk)
|
||
|
return (IVersion);
|
||
|
else
|
||
|
return ((short)0);
|
||
|
}
|
||
|
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#if !defined ENGINE /* TODO(RMS)-H 12/12/2005: ENGINE: refactor to use just the Interrupted flag as-is */
|
||
|
#else
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
/**********************************************************************
|
||
|
**********************************************************************
|
||
|
********************** OUTPUT **************************
|
||
|
**********************************************************************
|
||
|
**********************************************************************/
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Byte blocks cannot be unaligned or reversed in bytes
|
||
|
*/
|
||
|
Boolean_t WriteBinaryByteBlock(FileStream_s *FileStream,
|
||
|
const Byte_t *ByteValues,
|
||
|
const HgIndex_t NumValues)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(VALID_REF(ByteValues));
|
||
|
REQUIRE(NumValues >= 0);
|
||
|
|
||
|
Boolean_t IsOk = TP_FWRITE(ByteValues,
|
||
|
sizeof(Byte_t),
|
||
|
(size_t)NumValues,
|
||
|
FileStream->File) == (size_t)NumValues;
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Type Byte_t cannot be unaligned or reversed in byte order
|
||
|
*/
|
||
|
static inline Boolean_t WriteBinaryByte(FileStream_s *FileStream,
|
||
|
Byte_t ByteValue)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
Boolean_t IsOk = WriteBinaryByteBlock(FileStream, &ByteValue, 1);
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
template <typename T>
|
||
|
void CopyAndReverseUnalignedBytes(T *DstBuffer,
|
||
|
const Byte_t *SrcBuffer)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(DstBuffer));
|
||
|
REQUIRE(VALID_REF(SrcBuffer));
|
||
|
size_t typeSize = sizeof(T);
|
||
|
for (size_t ii = 0; ii < typeSize; ii++)
|
||
|
((Byte_t *)(DstBuffer))[ii] = ((Byte_t *)(SrcBuffer))[typeSize-1-ii];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
template <typename T>
|
||
|
void CopyUnalignedBytes(T *DstBuffer,
|
||
|
const Byte_t *SrcBuffer)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(DstBuffer));
|
||
|
REQUIRE(VALID_REF(SrcBuffer));
|
||
|
for (size_t ii = 0; ii < sizeof(T); ii++)
|
||
|
((Byte_t *)(DstBuffer))[ii] = ((Byte_t *)(SrcBuffer))[ii];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
template <typename T>
|
||
|
Boolean_t WriteBinaryDataUnaligned(FileStream_s *FileStream,
|
||
|
const Byte_t *ValueBuffer,
|
||
|
const Boolean_t ValueInNativeOrder)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_FILE_HANDLE(FileStream->File));
|
||
|
REQUIRE(VALID_REF(ValueBuffer));
|
||
|
REQUIRE(VALID_BOOLEAN(ValueInNativeOrder));
|
||
|
|
||
|
T DataValue;
|
||
|
if (ValueInNativeOrder != FileStream->IsByteOrderNative)
|
||
|
CopyAndReverseUnalignedBytes<T>(&DataValue, ValueBuffer);
|
||
|
else
|
||
|
CopyUnalignedBytes<T>(&DataValue, ValueBuffer);
|
||
|
|
||
|
Boolean_t IsOk = TP_FWRITE(&DataValue, sizeof(T), 1, FileStream->File) == 1;
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* This is used in many places and requires the value be in proper order.
|
||
|
*/
|
||
|
Boolean_t WriteBinaryInt16(FileStream_s *FileStream,
|
||
|
Int16_t Value)
|
||
|
{
|
||
|
Boolean_t IsOk;
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE("Value can be any Int16_t");
|
||
|
IsOk = WriteBinaryDataUnaligned<Int16_t>(FileStream, (Byte_t *) & Value, TRUE/*ValueInNativeOrder*/);
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This is used in many places and requires the value be in proper order.
|
||
|
*/
|
||
|
Boolean_t WriteBinaryInt32(FileStream_s *FileStream,
|
||
|
Int32_t Value)
|
||
|
{
|
||
|
Boolean_t IsOk;
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE("Value can be any Int32_t");
|
||
|
IsOk = WriteBinaryDataUnaligned<Int32_t>(FileStream, (Byte_t *) & Value, TRUE/*ValueInNativeOrder*/);
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
template <typename T>
|
||
|
Boolean_t WriteBinaryBlockUnaligned(FileStream_s *FileStream,
|
||
|
const Byte_t *Values,
|
||
|
const HgIndex_t NumValues,
|
||
|
const Boolean_t ValuesInNativeOrdering)
|
||
|
{
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
Boolean_t WriteEachValueSeparately;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(VALID_REF(Values));
|
||
|
REQUIRE(NumValues >= 0);
|
||
|
REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering));
|
||
|
|
||
|
WriteEachValueSeparately = (ValuesInNativeOrdering != FileStream->IsByteOrderNative);
|
||
|
|
||
|
if (WriteEachValueSeparately)
|
||
|
{
|
||
|
for (HgIndex_t NIndex = 0; IsOk && NIndex < NumValues; NIndex++)
|
||
|
{
|
||
|
IsOk = WriteBinaryDataUnaligned<T>(FileStream, Values + NIndex * sizeof(T), ValuesInNativeOrdering);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if 1
|
||
|
size_t NumBytesToWrite = NumValues * sizeof(T);
|
||
|
size_t NumBytesWritten = TP_FWRITE(Values, sizeof(Byte_t), NumBytesToWrite, FileStream->File);
|
||
|
IsOk = NumBytesToWrite == NumBytesWritten;
|
||
|
#else
|
||
|
IsOk = WriteBinaryByteBlock(FileStream, Values, NumValues * sizeof(T));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Use Byte_t instead of Int16_t to support unaligned values
|
||
|
*/
|
||
|
Boolean_t WriteBinaryInt16BlockUnaligned(FileStream_s *FileStream,
|
||
|
Byte_t *Int16Values,
|
||
|
HgIndex_t NumValues,
|
||
|
Boolean_t ValuesInNativeOrdering)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(VALID_REF(Int16Values));
|
||
|
REQUIRE(NumValues >= 0);
|
||
|
REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering));
|
||
|
|
||
|
Boolean_t IsOk = WriteBinaryBlockUnaligned<Int16_t>(FileStream,
|
||
|
Int16Values,
|
||
|
NumValues,
|
||
|
ValuesInNativeOrdering);
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Use Byte_t instead of Int32_t to support unaligned values
|
||
|
*/
|
||
|
Boolean_t WriteBinaryInt32BlockUnaligned(FileStream_s *FileStream,
|
||
|
Byte_t *Int32Values,
|
||
|
HgIndex_t NumValues,
|
||
|
Boolean_t ValuesInNativeOrdering)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(VALID_REF(Int32Values));
|
||
|
REQUIRE(NumValues >= 0);
|
||
|
REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering));
|
||
|
|
||
|
Boolean_t IsOk = WriteBinaryBlockUnaligned<Int32_t>(FileStream,
|
||
|
Int32Values,
|
||
|
NumValues,
|
||
|
ValuesInNativeOrdering);
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
Boolean_t WriteBinaryReal(FileStream_s *FileStream,
|
||
|
double RR,
|
||
|
FieldDataType_e FieldDataType)
|
||
|
{
|
||
|
Boolean_t IsOk = FALSE; /* ...quite compiler */
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE((FieldDataType == FieldDataType_Float) ||
|
||
|
(FieldDataType == FieldDataType_Double) ||
|
||
|
(FieldDataType == FieldDataType_Byte));
|
||
|
|
||
|
switch (FieldDataType)
|
||
|
{
|
||
|
case FieldDataType_Float :
|
||
|
{
|
||
|
float FloatVal = CONVERT_DOUBLE_TO_FLOAT(RR);
|
||
|
IsOk = WriteBinaryDataUnaligned<float>(FileStream, (Byte_t *) & FloatVal, TRUE/*NativeOrdering*/);
|
||
|
} break;
|
||
|
case FieldDataType_Double :
|
||
|
{
|
||
|
double DoubleVal = CLAMP_DOUBLE(RR);
|
||
|
IsOk = WriteBinaryDataUnaligned<double>(FileStream, (Byte_t *) & DoubleVal, TRUE/*NativeOrdering*/);
|
||
|
} break;
|
||
|
case FieldDataType_Byte :
|
||
|
{
|
||
|
/* Note: type Byte cannot be unaligned or reversed in bytes */
|
||
|
Byte_t B;
|
||
|
if (RR > 255)
|
||
|
B = 255;
|
||
|
else if (RR < 0)
|
||
|
B = 0;
|
||
|
else
|
||
|
B = (Byte_t)RR;
|
||
|
IsOk = WriteBinaryByte(FileStream, B);
|
||
|
} break;
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
Boolean_t WriteFieldDataType(FileStream_s *FileStream,
|
||
|
FieldDataType_e FDT,
|
||
|
Boolean_t WriteBinary)
|
||
|
{
|
||
|
if (WriteBinary)
|
||
|
return (WriteBinaryInt32(FileStream, (LgIndex_t)FDT));
|
||
|
else
|
||
|
{
|
||
|
short S = 0;
|
||
|
switch (FDT)
|
||
|
{
|
||
|
case FieldDataType_Float : S = fprintf(FileStream->File, "SINGLE "); break;
|
||
|
case FieldDataType_Double : S = fprintf(FileStream->File, "DOUBLE "); break;
|
||
|
case FieldDataType_Int32 : S = fprintf(FileStream->File, "LONGINT "); break;
|
||
|
case FieldDataType_Int16 : S = fprintf(FileStream->File, "SHORTINT "); break;
|
||
|
case FieldDataType_Byte : S = fprintf(FileStream->File, "BYTE "); break;
|
||
|
case FieldDataType_Bit : S = fprintf(FileStream->File, "BIT "); break;
|
||
|
default: CHECK(FALSE);
|
||
|
}
|
||
|
return (FPRINTFOK(S));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
template <typename T>
|
||
|
Boolean_t WriteBinaryChecksumByteValues(FileStream_s *FileStream,
|
||
|
const Byte_t *ByteValues,
|
||
|
const HgIndex_t NumValues)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_FILE_HANDLE(FileStream->File));
|
||
|
REQUIRE(VALID_REF(ByteValues));
|
||
|
REQUIRE(NumValues >= 1);
|
||
|
|
||
|
Boolean_t IsOk;
|
||
|
if (NumValues == 1)
|
||
|
IsOk = WriteBinaryDataUnaligned<T>(FileStream, ByteValues, TRUE);
|
||
|
else
|
||
|
IsOk = WriteBinaryBlockUnaligned<T>(FileStream, ByteValues, NumValues, TRUE);
|
||
|
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* For FieldData of Type Bit, use WriteBinaryFieldDataBlockOfTypeBit instead.
|
||
|
*/
|
||
|
template <typename T>
|
||
|
Boolean_t WriteBinaryFieldDataBlockOfType(FileStream_s *FileStream,
|
||
|
const FieldData_pa FieldData,
|
||
|
const LgIndex_t StartOffset,
|
||
|
const LgIndex_t NumValues)
|
||
|
{
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
|
||
|
Boolean_t IsOk = FALSE;
|
||
|
if (IsFieldDataDirectAccessAllowed(FieldData))
|
||
|
{
|
||
|
Byte_t *ByteArray = GetFieldDataBytePtr(FieldData) + StartOffset * sizeof(T);
|
||
|
IsOk = WriteBinaryChecksumByteValues<T>(FileStream, ByteArray, (HgIndex_t)NumValues);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (LgIndex_t Offset = StartOffset; Offset < NumValues; Offset++)
|
||
|
{
|
||
|
T ValueBuffer = (T)GetFieldValue(FieldData, Offset);
|
||
|
Byte_t *ByteValue = (Byte_t *) & ValueBuffer;
|
||
|
IsOk = WriteBinaryChecksumByteValues<T>(FileStream, ByteValue, 1);
|
||
|
}
|
||
|
}
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
static Boolean_t WriteBinaryFieldDataBlockOfTypeBit(FileStream_s *FileStream,
|
||
|
const FieldData_pa FieldData,
|
||
|
const LgIndex_t StartOffset, /* Not used */
|
||
|
const LgIndex_t NumValues)
|
||
|
{
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
|
||
|
Boolean_t IsOk = FALSE;
|
||
|
size_t NumBytes = 1 + (NumValues - 1) / 8;
|
||
|
if (IsFieldDataDirectAccessAllowed(FieldData))
|
||
|
{
|
||
|
Byte_t *ByteArray = GetFieldDataBytePtr(FieldData);
|
||
|
IsOk = WriteBinaryChecksumByteValues<Byte_t>(FileStream, ByteArray, (HgIndex_t)NumBytes);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Bits are written out a Byte at a time and since we only come in here every 8th
|
||
|
// bit, make sure to assemble a Byte value from the next 8 bits.
|
||
|
for (LgIndex_t Offset = 0; Offset < NumValues; Offset += 8)
|
||
|
{
|
||
|
Byte_t ValueBuffer = 0;
|
||
|
for (int ii = 0; ii < 8; ii++)
|
||
|
{
|
||
|
Byte_t CurBit = (Byte_t)GetFieldValue(FieldData, Offset + ii);
|
||
|
ValueBuffer |= (CurBit << ii);
|
||
|
}
|
||
|
IsOk = WriteBinaryChecksumByteValues<Byte_t>(FileStream, &ValueBuffer, 1);
|
||
|
}
|
||
|
}
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*/
|
||
|
Boolean_t WriteBinaryFieldDataBlock(FileStream_s *FileStream,
|
||
|
FieldData_pa FieldData,
|
||
|
LgIndex_t StartOffset,
|
||
|
LgIndex_t NumValues)
|
||
|
{
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
|
||
|
Boolean_t IsOk = FALSE;
|
||
|
switch (GetFieldDataType(FieldData))
|
||
|
{
|
||
|
case FieldDataType_Float : IsOk = WriteBinaryFieldDataBlockOfType<float>(FileStream, FieldData, StartOffset, NumValues); break;
|
||
|
case FieldDataType_Double : IsOk = WriteBinaryFieldDataBlockOfType<double>(FileStream, FieldData, StartOffset, NumValues); break;
|
||
|
case FieldDataType_Int32 : IsOk = WriteBinaryFieldDataBlockOfType<Int32_t>(FileStream, FieldData, StartOffset, NumValues); break;
|
||
|
case FieldDataType_Int16 : IsOk = WriteBinaryFieldDataBlockOfType<Int16_t>(FileStream, FieldData, StartOffset, NumValues); break;
|
||
|
case FieldDataType_Byte : IsOk = WriteBinaryFieldDataBlockOfType<Byte_t>(FileStream, FieldData, StartOffset, NumValues); break;
|
||
|
case FieldDataType_Bit : IsOk = WriteBinaryFieldDataBlockOfTypeBit(FileStream, FieldData, StartOffset, NumValues); break;
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
static Boolean_t WriteASCIIFieldDataValue(FileStream_s *FileStream,
|
||
|
FieldData_pa FieldData,
|
||
|
LgIndex_t Offset,
|
||
|
SmInteger_t AsciiPrecision)
|
||
|
{
|
||
|
Boolean_t IsOk = FALSE; /* ...quiet compiler */
|
||
|
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
|
||
|
double V = 0.0;
|
||
|
char buffer[100*MAX_SIZEOFUTF8CHAR];
|
||
|
char *AsciiValue = buffer;
|
||
|
|
||
|
#ifdef TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
|
||
|
V = GetFieldValue(FieldData, Offset);
|
||
|
|
||
|
switch (GetFieldDataType(FieldData))
|
||
|
{
|
||
|
case FieldDataType_Float :
|
||
|
case FieldDataType_Double :
|
||
|
/*IsOk = FPRINTFOK(fprintf(FileStream->File," %.*E",(int)AsciiPrecision,V)); */
|
||
|
sprintf(buffer, " %.*E", (int)AsciiPrecision, V);
|
||
|
break;
|
||
|
case FieldDataType_Int32 :
|
||
|
/* IsOk = FPRINTFOK(fprintf(FileStream->File," %*d",(int)AsciiPrecision,ROUNDL(V))); */
|
||
|
sprintf(buffer, " %*d", (int)AsciiPrecision, ROUNDL(V));
|
||
|
break;
|
||
|
case FieldDataType_Int16 :
|
||
|
/* IsOk = FPRINTFOK(fprintf(FileStream->File," %6d",ROUND2(V))); */
|
||
|
sprintf(buffer, " %6d", ROUND2(V));
|
||
|
break;
|
||
|
case FieldDataType_Byte :
|
||
|
/* IsOk = FPRINTFOK(fprintf(FileStream->File," %3d",ROUNDS(V))); */
|
||
|
sprintf(buffer, " %3d", ROUNDS(V));
|
||
|
break;
|
||
|
case FieldDataType_Bit :
|
||
|
/* IsOk = FPRINTFOK(fprintf(FileStream->File," %c",((V == 0) ? '0' : '1'))); */
|
||
|
sprintf(buffer, " %c", ((V == 0) ? '0' : '1'));
|
||
|
break;
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
IsOk = FPRINTFOK(fprintf(FileStream->File, buffer));
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#endif
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return (IsOk);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
Boolean_t WriteCCFieldDataBlock(FileStream_s *FileStream,
|
||
|
FieldData_pa FieldData,
|
||
|
Boolean_t IsOrderedData,
|
||
|
LgIndex_t NumIPts,
|
||
|
LgIndex_t NumJPts,
|
||
|
LgIndex_t NumKPts,
|
||
|
Boolean_t WriteBinary,
|
||
|
SmInteger_t AsciiPrecision)
|
||
|
{
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
LgIndex_t NumValues;
|
||
|
LgIndex_t I, J, K;
|
||
|
LgIndex_t NumIJPts = -1;
|
||
|
LgIndex_t IEnd = -1;
|
||
|
LgIndex_t JEnd = -1;
|
||
|
LgIndex_t KEnd = -1;
|
||
|
Boolean_t IsLinear = -1;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(VALID_REF(FieldData));
|
||
|
REQUIRE(VALID_BOOLEAN(IsOrderedData));
|
||
|
REQUIRE(NumIPts >= 0);
|
||
|
REQUIRE(NumJPts >= 0);
|
||
|
REQUIRE(NumKPts >= 0);
|
||
|
REQUIRE(VALID_BOOLEAN(WriteBinary));
|
||
|
REQUIRE(IMPLICATION(!WriteBinary, AsciiPrecision >= 0));
|
||
|
|
||
|
/*
|
||
|
* As of version 103 Tecplot writes binary data files so that ordered cell
|
||
|
* centered field data includes the ghost cells. This makes it much easier
|
||
|
* for Tecplot to map the data when reading by simply writing out
|
||
|
* FieldData->NumValues. As of version 104 the ghost cells of the slowest
|
||
|
* moving index are not included but that does effect the output as it is
|
||
|
* still FieldData->NumValues.
|
||
|
*/
|
||
|
if (IsOrderedData && !WriteBinary)
|
||
|
{
|
||
|
/*
|
||
|
* Ordered ASCII output is always layed out using
|
||
|
* DataValueStructure_Classic format.
|
||
|
*/
|
||
|
NumIJPts = NumIPts * NumJPts;
|
||
|
IEnd = MAX(NumIPts - 1, 1);
|
||
|
JEnd = MAX(NumJPts - 1, 1);
|
||
|
KEnd = MAX(NumKPts - 1, 1);
|
||
|
NumValues = (IEnd * JEnd * KEnd);
|
||
|
IsLinear = ((NumJPts == 1 && NumKPts == 1) ||
|
||
|
(NumIPts == 1 && NumKPts == 1) ||
|
||
|
(NumIPts == 1 && NumJPts == 1));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NumValues = GetFieldDataNumValues(FieldData);
|
||
|
}
|
||
|
|
||
|
if (WriteBinary)
|
||
|
{
|
||
|
IsOk = WriteBinaryFieldDataBlock(FileStream, FieldData, 0, NumValues);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LgIndex_t NumValuesPerLine = 80 / (AsciiPrecision + 5);
|
||
|
if (IsOrderedData && !IsLinear)
|
||
|
{
|
||
|
LgIndex_t ValueIndex = 0;
|
||
|
for (K = 0; K < KEnd && IsOk; K++)
|
||
|
for (J = 0; J < JEnd && IsOk; J++)
|
||
|
for (I = 0; I < IEnd && IsOk; I++)
|
||
|
{
|
||
|
LgIndex_t CellIndex = I + (J * NumIPts) + (K * NumIJPts);
|
||
|
IsOk = WriteASCIIFieldDataValue(FileStream,
|
||
|
FieldData,
|
||
|
CellIndex,
|
||
|
AsciiPrecision);
|
||
|
if ((ValueIndex + 1) % NumValuesPerLine == 0 || ValueIndex == NumValues - 1)
|
||
|
IsOk = (fputc('\n', FileStream->File) != EOF);
|
||
|
ValueIndex++;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (I = 0; I < NumValues && IsOk; I++)
|
||
|
{
|
||
|
IsOk = WriteASCIIFieldDataValue(FileStream,
|
||
|
FieldData,
|
||
|
I,
|
||
|
AsciiPrecision);
|
||
|
if ((I + 1) % NumValuesPerLine == 0 || I == NumValues - 1)
|
||
|
IsOk = (fputc('\n', FileStream->File) != EOF);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
Boolean_t DumpDatafileString(FileStream_s *FileStream,
|
||
|
const char *S,
|
||
|
Boolean_t WriteBinary)
|
||
|
{
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
const char *CPtr = S;
|
||
|
if (WriteBinary)
|
||
|
{
|
||
|
const char *CPtr = S;
|
||
|
while (IsOk && CPtr && *CPtr)
|
||
|
IsOk = WriteBinaryInt32(FileStream, (LgIndex_t)(unsigned char) * CPtr++);
|
||
|
if (IsOk)
|
||
|
IsOk = WriteBinaryInt32(FileStream, 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fputc('"', FileStream->File);
|
||
|
while (CPtr && *CPtr)
|
||
|
{
|
||
|
if (*CPtr == '\n')
|
||
|
{
|
||
|
CPtr++;
|
||
|
fputc('\\', FileStream->File);
|
||
|
fputc('\\', FileStream->File);
|
||
|
fputc('n', FileStream->File);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ((*CPtr == '"') || (*CPtr == '\\'))
|
||
|
fputc('\\', FileStream->File);
|
||
|
fputc(*CPtr++, FileStream->File);
|
||
|
}
|
||
|
}
|
||
|
fputc('"', FileStream->File);
|
||
|
IsOk = (fputc('\n', FileStream->File) != EOF);
|
||
|
}
|
||
|
return (IsOk);
|
||
|
}
|
||
|
|
||
|
|
||
|
static void WriteAsciiColor(FILE *File,
|
||
|
ColorIndex_t Color)
|
||
|
{
|
||
|
if (Color >= FirstCustomColor && Color <= LastCustomColor)
|
||
|
fprintf(File, "CUST%1d ", Color - FirstCustomColor + 1);
|
||
|
else
|
||
|
{
|
||
|
switch (Color)
|
||
|
{
|
||
|
case Black_C : fprintf(File, "BLACK "); break;
|
||
|
case Red_C : fprintf(File, "RED "); break;
|
||
|
case Green_C : fprintf(File, "GREEN "); break;
|
||
|
case Blue_C : fprintf(File, "BLUE "); break;
|
||
|
case Cyan_C : fprintf(File, "CYAN "); break;
|
||
|
case Yellow_C : fprintf(File, "YELLOW "); break;
|
||
|
case Purple_C : fprintf(File, "PURPLE "); break;
|
||
|
case White_C : fprintf(File, "WHITE "); break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void WriteAsciiTextGeomBasics(FILE* File,
|
||
|
CoordSys_e CoordSys,
|
||
|
Boolean_t AttachToZone,
|
||
|
EntIndex_t Zone,
|
||
|
ColorIndex_t Color,
|
||
|
Scope_e Scope,
|
||
|
Boolean_t IncludeZ,
|
||
|
Boolean_t WriteGridDataAsPolar,
|
||
|
AnchorPos_u const* AnchorPos,
|
||
|
double ScaleFact)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(File));
|
||
|
REQUIRE(VALID_TEXT_COORDSYS(CoordSys) || VALID_GEOM_COORDSYS(CoordSys));
|
||
|
REQUIRE(VALID_BOOLEAN(AttachToZone));
|
||
|
REQUIRE(IMPLICATION(AttachToZone, Zone >= 0));
|
||
|
REQUIRE(VALID_ENUM(Scope, Scope_e));
|
||
|
REQUIRE(VALID_BOOLEAN(IncludeZ));
|
||
|
REQUIRE(VALID_BOOLEAN(WriteGridDataAsPolar));
|
||
|
REQUIRE(VALID_REF(AnchorPos));
|
||
|
|
||
|
fprintf(File, "CS=");
|
||
|
if (CoordSys == CoordSys_Frame)
|
||
|
fprintf(File, "FRAME");
|
||
|
else if (CoordSys == CoordSys_Grid)
|
||
|
fprintf(File, "GRID");
|
||
|
/*
|
||
|
* Not currently used
|
||
|
*
|
||
|
else if (CoordSys == CoordSys_FrameOffset)
|
||
|
fprintf(File,"FRAMEOFFSET");
|
||
|
*/
|
||
|
else if (CoordSys == CoordSys_Grid3D)
|
||
|
fprintf(File, "GRID3D");
|
||
|
else
|
||
|
CHECK(FALSE);
|
||
|
|
||
|
if (CoordSys == CoordSys_Grid && !IncludeZ && WriteGridDataAsPolar)
|
||
|
{
|
||
|
fprintf(File, "\nTHETA=%.12G,R=%.12G",
|
||
|
ScaleFact*AnchorPos->ThetaR.Theta,
|
||
|
ScaleFact*AnchorPos->ThetaR.R);
|
||
|
CHECK(!IncludeZ);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fprintf(File, "\nX=%.12G,Y=%.12G",
|
||
|
ScaleFact*AnchorPos->XYZ.X,
|
||
|
ScaleFact*AnchorPos->XYZ.Y);
|
||
|
if (IncludeZ)
|
||
|
fprintf(File, ",Z=%.12G", ScaleFact*AnchorPos->XYZ.Z);
|
||
|
}
|
||
|
|
||
|
if (AttachToZone)
|
||
|
fprintf(File, "\nZN=%d", Zone + 1);
|
||
|
|
||
|
fprintf(File, "\nC=");
|
||
|
WriteAsciiColor(File, Color);
|
||
|
|
||
|
fprintf(File, "\nS=");
|
||
|
if (Scope == Scope_Global)
|
||
|
fprintf(File, "GLOBAL");
|
||
|
else if (Scope == Scope_Local)
|
||
|
fprintf(File, "LOCAL");
|
||
|
else
|
||
|
CHECK(FALSE);
|
||
|
|
||
|
fputc('\n', File);
|
||
|
}
|
||
|
|
||
|
|
||
|
bool DumpGeometry(FileStream_s* FileStream,
|
||
|
Geom_s const* Geom,
|
||
|
Boolean_t WriteBinary,
|
||
|
Boolean_t WriteGridDataAsPolar)
|
||
|
{
|
||
|
LgIndex_t I, Index;
|
||
|
LgIndex_t SegIndex;
|
||
|
bool IsOk = TRUE;
|
||
|
FieldDataType_e FDT;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(VALID_REF(Geom));
|
||
|
REQUIRE(Geom->GeomType != GeomType_Image);
|
||
|
|
||
|
if (WriteBinary)
|
||
|
{
|
||
|
WriteBinaryReal(FileStream, GeomMarker, FieldDataType_Float);
|
||
|
if (Geom->PositionCoordSys == CoordSys_Grid)
|
||
|
WriteBinaryInt32(FileStream, 0);
|
||
|
else if (Geom->PositionCoordSys == CoordSys_Frame)
|
||
|
WriteBinaryInt32(FileStream, 1);
|
||
|
#if 0 /*
|
||
|
* Not currently used
|
||
|
*/
|
||
|
else if (Geom->PositionCoordSys == CoordSys_FrameOffset)
|
||
|
WriteBinaryInt32(FileStream, 2);
|
||
|
#endif
|
||
|
/*
|
||
|
* PositionCoordSys == 3 is for old window coordinate system
|
||
|
*/
|
||
|
else if (Geom->PositionCoordSys == CoordSys_Grid3D)
|
||
|
WriteBinaryInt32(FileStream, 4);
|
||
|
else
|
||
|
CHECK(FALSE);
|
||
|
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Scope);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->DrawOrder);
|
||
|
WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V1, FieldDataType_Double);
|
||
|
WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V2, FieldDataType_Double);
|
||
|
WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V3, FieldDataType_Double);
|
||
|
if (Geom->AttachToZone)
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Zone);
|
||
|
else
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t) - 1);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->BColor);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->FillBColor);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->IsFilled);
|
||
|
CHECK(Geom->GeomType != GeomType_LineSegs3D); /* deprecated */
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->GeomType);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->LinePattern);
|
||
|
WriteBinaryReal(FileStream, Geom->PatternLength, FieldDataType_Double);
|
||
|
WriteBinaryReal(FileStream, Geom->LineThickness, FieldDataType_Double);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->NumEllipsePts);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->ArrowheadStyle);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->ArrowheadAttachment);
|
||
|
WriteBinaryReal(FileStream, Geom->ArrowheadSize, FieldDataType_Double);
|
||
|
|
||
|
WriteBinaryReal(FileStream, Geom->ArrowheadAngle, FieldDataType_Double);
|
||
|
|
||
|
/* MACRO FUNCTION COMMAND */
|
||
|
DumpDatafileString(FileStream, Geom->MacroFunctionCommand, TRUE);
|
||
|
|
||
|
/*
|
||
|
* Assume geometry has X,Y (and Z) all using same field
|
||
|
* data type.
|
||
|
*/
|
||
|
FDT = GetGeomFieldDataType(Geom);
|
||
|
WriteFieldDataType(FileStream, FDT, TRUE);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Clipping);
|
||
|
|
||
|
if (Geom->GeomType == GeomType_LineSegs)
|
||
|
{
|
||
|
short S;
|
||
|
WriteBinaryInt32(FileStream, Geom->NumSegments);
|
||
|
I = 0;
|
||
|
for (S = 0; IsOk && (S < Geom->NumSegments); S++)
|
||
|
{
|
||
|
WriteBinaryInt32(FileStream, Geom->NumSegPts[S]);
|
||
|
WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V1Base, I, Geom->NumSegPts[S]);
|
||
|
IsOk = WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V2Base, I, Geom->NumSegPts[S]) == TRUE;
|
||
|
if (Geom->PositionCoordSys == CoordSys_Grid3D)
|
||
|
IsOk = WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V3Base, I, Geom->NumSegPts[S]) == TRUE;
|
||
|
I += Geom->NumSegPts[S];
|
||
|
}
|
||
|
}
|
||
|
else if (Geom->GeomType == GeomType_Rectangle ||
|
||
|
Geom->GeomType == GeomType_Ellipse)
|
||
|
{
|
||
|
WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.XBase, 0), FDT);
|
||
|
IsOk = WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.YBase, 0), FDT) == TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CHECK((Geom->GeomType == GeomType_Square) ||
|
||
|
(Geom->GeomType == GeomType_Circle));
|
||
|
IsOk = WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.XBase, 0), FDT) == TRUE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
double ScaleFact;
|
||
|
if (Geom->PositionCoordSys == CoordSys_Frame)
|
||
|
ScaleFact = 100.0;
|
||
|
else
|
||
|
ScaleFact = 1.0;
|
||
|
|
||
|
fprintf(FileStream->File, "GEOMETRY\nF=POINT\n");
|
||
|
WriteAsciiTextGeomBasics(FileStream->File,
|
||
|
Geom->PositionCoordSys,
|
||
|
Geom->AttachToZone,
|
||
|
Geom->Zone,
|
||
|
Geom->BColor,
|
||
|
Geom->Scope,
|
||
|
TRUE,
|
||
|
WriteGridDataAsPolar,
|
||
|
&Geom->AnchorPos,
|
||
|
ScaleFact);
|
||
|
|
||
|
switch (Geom->LinePattern)
|
||
|
{
|
||
|
case LinePattern_Solid : fprintf(FileStream->File, "L=SOLID\n"); break;
|
||
|
case LinePattern_Dashed : fprintf(FileStream->File, "L=DASHED\n"); break;
|
||
|
case LinePattern_DashDot : fprintf(FileStream->File, "L=DASHDOT\n"); break;
|
||
|
case LinePattern_Dotted : fprintf(FileStream->File, "L=DOTTED\n"); break;
|
||
|
case LinePattern_LongDash : fprintf(FileStream->File, "L=LONGDASH\n"); break;
|
||
|
case LinePattern_DashDotDot : fprintf(FileStream->File, "L=DASHDOTDOT\n"); break;
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
fprintf(FileStream->File, "PL=%.12G\n",
|
||
|
Geom->PatternLength*PatternLengthInputSpec.InterfaceAdjust.ScaleFact);
|
||
|
fprintf(FileStream->File, "LT=%.12G\n",
|
||
|
Geom->LineThickness*LineThicknessInputSpec.InterfaceAdjust.ScaleFact);
|
||
|
|
||
|
if (Geom->IsFilled)
|
||
|
{
|
||
|
fprintf(FileStream->File, "FC=");
|
||
|
WriteAsciiColor(FileStream->File, Geom->FillBColor);
|
||
|
}
|
||
|
|
||
|
if (Geom->Clipping == Clipping_ClipToViewport)
|
||
|
fprintf(FileStream->File, "CLIPPING=CLIPTOVIEWPORT\n");
|
||
|
else if (Geom->Clipping == Clipping_ClipToFrame)
|
||
|
fprintf(FileStream->File, "CLIPPING=CLIPTOFRAME\n");
|
||
|
else
|
||
|
CHECK(FALSE);
|
||
|
|
||
|
if (Geom->DrawOrder == DrawOrder_AfterData)
|
||
|
fprintf(FileStream->File, "DRAWORDER=AFTERDATA\n");
|
||
|
else if (Geom->DrawOrder == DrawOrder_BeforeData)
|
||
|
fprintf(FileStream->File, "DRAWORDER=BEFOREDATA\n");
|
||
|
else
|
||
|
CHECK(FALSE);
|
||
|
|
||
|
/* Macro function command */
|
||
|
fprintf(FileStream->File, "MFC=");
|
||
|
DumpDatafileString(FileStream, Geom->MacroFunctionCommand, FALSE);
|
||
|
|
||
|
if ((Geom->GeomType == GeomType_Circle) || (Geom->GeomType == GeomType_Ellipse))
|
||
|
fprintf(FileStream->File, "EP=%ld\n", (long)Geom->NumEllipsePts);
|
||
|
|
||
|
if (Geom->GeomType == GeomType_LineSegs && Geom->PositionCoordSys != CoordSys_Grid3D)
|
||
|
{
|
||
|
switch (Geom->ArrowheadStyle)
|
||
|
{
|
||
|
case ArrowheadStyle_Plain : fprintf(FileStream->File, "AST=PLAIN\n"); break;
|
||
|
case ArrowheadStyle_Filled : fprintf(FileStream->File, "AST=FILLED\n"); break;
|
||
|
case ArrowheadStyle_Hollow : fprintf(FileStream->File, "AST=HOLLOW\n"); break;
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
|
||
|
switch (Geom->ArrowheadAttachment)
|
||
|
{
|
||
|
case ArrowheadAttachment_None : break;
|
||
|
case ArrowheadAttachment_AtBeginning : fprintf(FileStream->File, "AAT=BEGINNING\n"); break;
|
||
|
case ArrowheadAttachment_AtEnd : fprintf(FileStream->File, "AAT=END\n"); break;
|
||
|
case ArrowheadAttachment_AtBothEnds : fprintf(FileStream->File, "AAT=BOTH\n"); break;
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
if (Geom->ArrowheadAttachment != ArrowheadAttachment_None)
|
||
|
{
|
||
|
fprintf(FileStream->File, "ASZ=%.12G\n",
|
||
|
Geom->ArrowheadSize*ArrowheadSizeInputSpec.InterfaceAdjust.ScaleFact);
|
||
|
fprintf(FileStream->File, "AAN=%.12G\n",
|
||
|
Geom->ArrowheadAngle*ArrowheadAngleInputSpec.InterfaceAdjust.ScaleFact);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch (Geom->GeomType)
|
||
|
{
|
||
|
case GeomType_LineSegs :
|
||
|
{
|
||
|
fprintf(FileStream->File, "T=LINE\n");
|
||
|
fprintf(FileStream->File, "DT=");
|
||
|
WriteFieldDataType(FileStream, GetFieldDataType(Geom->GeomData.Generic.V1Base), FALSE);
|
||
|
fputc('\n', FileStream->File);
|
||
|
fprintf(FileStream->File, "%d\n", (int)Geom->NumSegments);
|
||
|
SegIndex = 0;
|
||
|
for (I = 0; IsOk && (I < Geom->NumSegments); I++)
|
||
|
{
|
||
|
fprintf(FileStream->File, "%ld\n", (long)Geom->NumSegPts[I]);
|
||
|
for (Index = 0; Index < Geom->NumSegPts[I]; Index++)
|
||
|
{
|
||
|
fprintf(FileStream->File, "%.12G ", GetFieldValue(Geom->GeomData.Generic.V1Base, SegIndex + Index)*ScaleFact);
|
||
|
fprintf(FileStream->File, "%.12G", GetFieldValue(Geom->GeomData.Generic.V2Base, SegIndex + Index)*ScaleFact);
|
||
|
if (Geom->PositionCoordSys == CoordSys_Grid3D)
|
||
|
IsOk = FPRINTFOK(fprintf(FileStream->File, " %.12G\n", GetFieldValue(Geom->GeomData.Generic.V3Base, SegIndex + Index)));
|
||
|
else
|
||
|
IsOk = (Boolean_t)(fputc('\n', FileStream->File) != EOF);
|
||
|
}
|
||
|
SegIndex += Geom->NumSegPts[I];
|
||
|
}
|
||
|
} break;
|
||
|
case GeomType_Rectangle :
|
||
|
{
|
||
|
fprintf(FileStream->File, "T=RECTANGLE %.12G %.12G\n",
|
||
|
GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact,
|
||
|
GetFieldValue(Geom->GeomData.XYZ.YBase, 0)*ScaleFact);
|
||
|
} break;
|
||
|
case GeomType_Square :
|
||
|
{
|
||
|
fprintf(FileStream->File, "T=SQUARE %.12G\n",
|
||
|
GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact);
|
||
|
} break;
|
||
|
case GeomType_Circle :
|
||
|
{
|
||
|
fprintf(FileStream->File, "T=CIRCLE %.12G\n",
|
||
|
GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact);
|
||
|
} break;
|
||
|
case GeomType_Ellipse :
|
||
|
{
|
||
|
fprintf(FileStream->File, "T=ELLIPSE %.12G %.12G\n",
|
||
|
GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact,
|
||
|
GetFieldValue(Geom->GeomData.XYZ.YBase, 0)*ScaleFact);
|
||
|
} break;
|
||
|
default: CHECK(FALSE);
|
||
|
}
|
||
|
}
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
bool DumpText(FileStream_s* FileStream,
|
||
|
Text_s const* Text,
|
||
|
Boolean_t WriteBinary,
|
||
|
Boolean_t WriteGridDataAsPolar)
|
||
|
{
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(VALID_REF(Text));
|
||
|
REQUIRE(VALID_BOOLEAN(WriteBinary));
|
||
|
REQUIRE(VALID_BOOLEAN(WriteGridDataAsPolar));
|
||
|
|
||
|
if (WriteBinary)
|
||
|
{
|
||
|
WriteBinaryReal(FileStream, TextMarker, FieldDataType_Float);
|
||
|
if (Text->PositionCoordSys == CoordSys_Grid)
|
||
|
WriteBinaryInt32(FileStream, 0);
|
||
|
else if (Text->PositionCoordSys == CoordSys_Frame)
|
||
|
WriteBinaryInt32(FileStream, 1);
|
||
|
#if 0 /*
|
||
|
* Not currently used
|
||
|
*/
|
||
|
else if (Geom->PositionCoordSys == CoordSys_FrameOffset)
|
||
|
WriteBinaryInt32(FileStream, 2);
|
||
|
#endif
|
||
|
/*
|
||
|
* 3 is used for old window coordinate system
|
||
|
*/
|
||
|
else if (Text->PositionCoordSys == CoordSys_Grid3D)
|
||
|
WriteBinaryInt32(FileStream, 4);
|
||
|
else
|
||
|
CHECK(FALSE);
|
||
|
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Scope);
|
||
|
WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V1, FieldDataType_Double);
|
||
|
WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V2, FieldDataType_Double);
|
||
|
WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V3, FieldDataType_Double);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Text->TextShape.Font);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Text->TextShape.SizeUnits);
|
||
|
WriteBinaryReal(FileStream, Text->TextShape.Height, FieldDataType_Double);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.BoxType);
|
||
|
WriteBinaryReal(FileStream, Text->Box.Margin, FieldDataType_Double);
|
||
|
WriteBinaryReal(FileStream, Text->Box.LineThickness, FieldDataType_Double);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.BColor);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.FillBColor);
|
||
|
WriteBinaryReal(FileStream, Text->Angle, FieldDataType_Double);
|
||
|
WriteBinaryReal(FileStream, Text->LineSpacing, FieldDataType_Double);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Anchor);
|
||
|
if (Text->AttachToZone)
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Zone);
|
||
|
else
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t) - 1);
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Text->BColor);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
double ScaleFact;
|
||
|
Boolean_t IncludeZ = Text->PositionCoordSys == CoordSys_Grid3D;
|
||
|
if (Text->PositionCoordSys == CoordSys_Frame)
|
||
|
ScaleFact = 100.0;
|
||
|
else
|
||
|
ScaleFact = 1.0;
|
||
|
fprintf(FileStream->File, "TEXT\n");
|
||
|
WriteAsciiTextGeomBasics(FileStream->File,
|
||
|
Text->PositionCoordSys,
|
||
|
Text->AttachToZone,
|
||
|
Text->Zone,
|
||
|
Text->BColor,
|
||
|
Text->Scope,
|
||
|
IncludeZ,
|
||
|
WriteGridDataAsPolar,
|
||
|
&Text->AnchorPos,
|
||
|
ScaleFact);
|
||
|
fprintf(FileStream->File, "HU=");
|
||
|
switch (Text->TextShape.SizeUnits)
|
||
|
{
|
||
|
case Units_Grid : fprintf(FileStream->File, "GRID\n"); break;
|
||
|
case Units_Frame : fprintf(FileStream->File, "FRAME\n"); break;
|
||
|
case Units_Point : fprintf(FileStream->File, "POINT\n"); break;
|
||
|
case Units_AxisPercentage : /* Not allowed */
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
|
||
|
fprintf(FileStream->File, "LS=%.4G ", Text->LineSpacing);
|
||
|
|
||
|
fprintf(FileStream->File, "AN=");
|
||
|
switch (Text->Anchor)
|
||
|
{
|
||
|
case TextAnchor_Left : fprintf(FileStream->File, "LEFT\n"); break;
|
||
|
case TextAnchor_Center : fprintf(FileStream->File, "CENTER\n"); break;
|
||
|
case TextAnchor_Right : fprintf(FileStream->File, "RIGHT\n"); break;
|
||
|
case TextAnchor_MidLeft : fprintf(FileStream->File, "MIDLEFT\n"); break;
|
||
|
case TextAnchor_MidCenter : fprintf(FileStream->File, "MIDCENTER\n"); break;
|
||
|
case TextAnchor_MidRight : fprintf(FileStream->File, "MIDRIGHT\n"); break;
|
||
|
case TextAnchor_HeadLeft : fprintf(FileStream->File, "HEADLEFT\n"); break;
|
||
|
case TextAnchor_HeadCenter : fprintf(FileStream->File, "HEADCENTER\n"); break;
|
||
|
case TextAnchor_HeadRight : fprintf(FileStream->File, "HEADRIGHT\n"); break;
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
|
||
|
switch (Text->Box.BoxType)
|
||
|
{
|
||
|
case TextBox_Hollow : fprintf(FileStream->File, "BX=Hollow "); break;
|
||
|
case TextBox_Filled : fprintf(FileStream->File, "BX=Filled "); break;
|
||
|
default :;
|
||
|
}
|
||
|
fprintf(FileStream->File, "BXM=%.4G ", Text->Box.Margin*100);
|
||
|
fprintf(FileStream->File, "LT=%.4G ", Text->Box.LineThickness*100.0);
|
||
|
fprintf(FileStream->File, "BXO="); WriteAsciiColor(FileStream->File, Text->Box.BColor);
|
||
|
fprintf(FileStream->File, "BXF="); WriteAsciiColor(FileStream->File, Text->Box.FillBColor);
|
||
|
|
||
|
fprintf(FileStream->File, "\nF=");
|
||
|
switch (Text->TextShape.Font)
|
||
|
{
|
||
|
case Font_Helvetica : fprintf(FileStream->File, "HELV"); break;
|
||
|
case Font_HelveticaBold : fprintf(FileStream->File, "HELV-BOLD"); break;
|
||
|
case Font_Times : fprintf(FileStream->File, "TIMES"); break;
|
||
|
case Font_TimesBold: fprintf(FileStream->File, "TIMES-BOLD"); break;
|
||
|
case Font_TimesItalic : fprintf(FileStream->File, "TIMES-ITALIC"); break;
|
||
|
case Font_TimesItalicBold : fprintf(FileStream->File, "TIMES-ITALIC-BOLD"); break;
|
||
|
case Font_Courier : fprintf(FileStream->File, "COURIER"); break;
|
||
|
case Font_CourierBold : fprintf(FileStream->File, "COURIER-BOLD"); break;
|
||
|
case Font_Greek : fprintf(FileStream->File, "GREEK"); break;
|
||
|
case Font_Math : fprintf(FileStream->File, "MATH"); break;
|
||
|
case Font_UserDefined : fprintf(FileStream->File, "USER-DEF"); break;
|
||
|
default: CHECK(FALSE); break;
|
||
|
}
|
||
|
if (Text->TextShape.SizeUnits == Units_Frame)
|
||
|
ScaleFact = 100.0;
|
||
|
else
|
||
|
ScaleFact = 1.0;
|
||
|
fprintf(FileStream->File, "\nH=%.12G A=%.12G",
|
||
|
Text->TextShape.Height*ScaleFact,
|
||
|
Text->Angle*DEGPERRADIANS);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (!WriteBinary)
|
||
|
fprintf(FileStream->File, "\nMFC=");
|
||
|
|
||
|
DumpDatafileString(FileStream, Text->MacroFunctionCommand, WriteBinary);
|
||
|
|
||
|
if (!WriteBinary)
|
||
|
{
|
||
|
if (Text->Clipping == Clipping_ClipToViewport)
|
||
|
fprintf(FileStream->File, "CLIPPING=CLIPTOVIEWPORT\n");
|
||
|
else if (Text->Clipping == Clipping_ClipToFrame)
|
||
|
fprintf(FileStream->File, "CLIPPING=CLIPTOFRAME\n");
|
||
|
else
|
||
|
CHECK(FALSE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Clipping);
|
||
|
}
|
||
|
|
||
|
if (!WriteBinary)
|
||
|
fprintf(FileStream->File, "T=");
|
||
|
|
||
|
return DumpDatafileString(FileStream, Text->Text, WriteBinary) == TRUE;
|
||
|
}
|
||
|
|
||
|
Boolean_t DumpCustomAxisLabels(FileStream_s *FileStream,
|
||
|
Boolean_t WriteBinary,
|
||
|
StringList_pa LabelBase)
|
||
|
{
|
||
|
Boolean_t IsOk = TRUE;
|
||
|
LgIndex_t Index = 0;
|
||
|
LgIndex_t Count = 0;
|
||
|
|
||
|
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
|
||
|
REQUIRE(VALID_BOOLEAN(WriteBinary));
|
||
|
REQUIRE(StringListValid(LabelBase));
|
||
|
|
||
|
Count = StringListCount(LabelBase);
|
||
|
if (WriteBinary)
|
||
|
{
|
||
|
WriteBinaryReal(FileStream, CustomLabelMarker, FieldDataType_Float);
|
||
|
WriteBinaryInt32(FileStream, Count);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fprintf(FileStream->File, " CUSTOMLABELS = \n");
|
||
|
}
|
||
|
|
||
|
for (Index = 0, IsOk = TRUE; Index < Count && IsOk; Index++)
|
||
|
{
|
||
|
const char *CurLabel = StringListGetStringRef(LabelBase, Index);
|
||
|
IsOk = DumpDatafileString(FileStream, CurLabel, WriteBinary);
|
||
|
}
|
||
|
|
||
|
ENSURE(VALID_BOOLEAN(IsOk));
|
||
|
return IsOk;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
Boolean_t WriteBinaryMagic(FileStream_s *FileStream)
|
||
|
{
|
||
|
/*
|
||
|
* Write an integer value of 1 to the file. This is used
|
||
|
* by the reader to determine byte order of the file.
|
||
|
*/
|
||
|
return (WriteBinaryInt32(FileStream, 1));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
bool writeBinaryVersionNumber(FileStream_s& fileStream,
|
||
|
int versionNumber)
|
||
|
{
|
||
|
char buffer[5];
|
||
|
sprintf(buffer,
|
||
|
"V%-3d",
|
||
|
versionNumber);
|
||
|
CHECK(strlen(buffer) == 4);
|
||
|
return fprintf(fileStream.File,
|
||
|
"#!TD%s",
|
||
|
buffer) > 0;
|
||
|
}
|
||
|
|
||
|
#if defined TECPLOTKERNEL
|
||
|
/* CORE SOURCE CODE REMOVED */
|
||
|
#if !defined SUN
|
||
|
#else
|
||
|
#endif
|
||
|
#if !defined NO_ASSERTS
|
||
|
#endif
|
||
|
#if defined ALLOW_USERDEF_NO_NEIGHBORING_ELEMENT
|
||
|
#else
|
||
|
#endif
|
||
|
#if 0 /* not used yet */
|
||
|
#endif
|
||
|
#if defined TECPLOTKERNEL
|
||
|
#endif
|
||
|
#if defined TECPLOTKERNEL
|
||
|
#endif
|
||
|
#endif
|