G3dIO.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, July 22, 1992 1:33 pm PDT
Ken Fishkin, August 20, 1992 4:02 pm PDT
DIRECTORY Atom, G3dBasic, G3dMatrix, IO, Rope, TiogaAccess;
G3dIO: CEDAR DEFINITIONS
~ BEGIN
Type Declarations
Imported Types
PropList:    TYPE ~ Atom.PropList;
IntegerSequence:  TYPE ~ G3dBasic.IntegerSequence;
NatSequence:   TYPE ~ G3dBasic.NatSequence;
Pair:     TYPE ~ G3dBasic.Pair;
PairSequence:  TYPE ~ G3dBasic.PairSequence;
Quad:     TYPE ~ G3dBasic.Quad;
RealSequence:  TYPE ~ G3dBasic.RealSequence;
SurfaceSequence: TYPE ~ G3dBasic.SurfaceSequence;
Triple:    TYPE ~ G3dBasic.Triple;
TripleSequence:  TYPE ~ G3dBasic.TripleSequence;
Matrix:    TYPE ~ G3dMatrix.Matrix;
STREAM:    TYPE ~ IO.STREAM;
ROPE:     TYPE ~ Rope.ROPE;
Writer:    TYPE ~ TiogaAccess.Writer;
Local Types
FieldType:   TYPE ~ {integer, real, pair, triple, nats, none};
FieldDescription: TYPE ~ RECORD [id: ROPE, type: FieldType];
Field:     TYPE ~ REF FieldRep;
FieldRep:    TYPE ~ RECORD [
id:        ROPE,        -- name of the field
type:       FieldType,      -- type of the field
sequence:      REF ANY       -- ref to field sequence
];
FieldSequence:  TYPE ~ REF FieldSequenceRep;
FieldSequenceRep: TYPE ~ RECORD [
length:      NAT,
element:      SEQUENCE maxLength: INTEGER OF Field
];
Line:     TYPE ~ REF LineRep;
LineRep:    TYPE ~ RECORD [
type:       {key, blank, data, comment}, -- type of line
rope:       ROPE ¬ NIL,      -- text of this line
index:       INTEGER ¬ 0,     -- current index into the rope
length:       INTEGER ¬ 0,     -- length of the rope
stream:      STREAM ¬ NIL     -- the associated io stream
];
File Format
Data in a G3dIO file is preceded by a separate keyLine that specifyies the data format.
This keyLine is a keyWord followed by a `~' and an arbitrary number of field descriptions.
The field descriptions, optionally be separated by commas, consist of a colon-terminated
identifier and a case-insensitive fieldType.
A sample keyLine is:
PointSet~ id: Integer, xyzCoords: Triple, rgbColor: Triple
The data following a keyLine is terminated by another keyLine or by end of file. Any line
that is not a keyLine, is not a blank line, and does not begin with "--" is a dataLine and is
assumed to contain valid data whose format is defined by the preceding keyLine.
Whitespace may appear before any of the punctuations ('~', ':', or ',').
Comments begin with "--"; they may be a separate line within the file or may terminate a
dataLine or keyLine.
The file is presumed Tioga formatted. If the file is opened elsewhere, its streamOption.tiogaRead
must be TRUE; otherwise Tioga formatting at the end of the file will be mistaken for data.
Errors
ErrorType: TYPE ~ {notFound, format, convert};
Error: ERROR [reason, lineText: ROPE, lineNumber: NAT];
ErrorReport: PROC [errorType: ErrorType, line: Line ¬ NIL, keyWord: ROPE ¬ NIL];
Raises Error with the proper reason.
Procedures that take a keyWord as an argument may raise ERROR Error["keyWord not found"].
Procedures that return data may raise ERROR Error["bad conversion"].
Procedures that fail to find expected data may raise ERROR ["bad format"].
Support Procedures
ObtainLine: PROC RETURNS [Line];
Obtain a line from the pool.
ReleaseLine: PROC [line: Line];
Release the line back to the pool.
LineNumber: PROC [line: Line] RETURNS [INTEGER];
Return the line number at which line occurs within the file; return -1 if not found.
NextKeyWord: PROC [
stream: STREAM,
circularSearch: BOOL ¬ FALSE,
maxNLinesToTest: CARDINAL ¬ LAST[CARDINAL]]
RETURNS [key: ROPE];
Return the next keyWord. The file index points to the beginning of the key line.
The keyWord search terminates after maxLinesToTest lines have been searched.
FindKeyWord: PROC [
stream: STREAM,
keyWord: ROPE,
circularSearch: BOOL ¬ FALSE,
maxNLinesToTest: CARDINAL ¬ LAST[CARDINAL],
line: Line ¬ NIL]
RETURNS [Line];
Return the line beginning with keyWord followed by "~"; line is returned with its index set
to after the "~". If line is passed non-NIL, it is used for storage.
The file index points to the beginning of the line following the key line.
The keyWord search terminates after maxLinesToTest lines have been searched.
InitializeFields: PROC [keyLine: Line] RETURNS [FieldSequence];
Allocate the fields for this keyLine, set their id's and types, but not their sequences.
NumberOfLinesToConvert: PROC [stream: STREAM] RETURNS [INTEGER];
Return the number of lines before next keyLine that are non-blank and non-comment.
This will not alter the stream pointer.
NWordsInRope: PROC [line: ROPE] RETURNS [INTEGER];
Return the number of words in the line.
Get Procedures
GetStream: PROC [fileName: ROPE] RETURNS [STREAM];
Return the opened filestream (or NIL if error in opening file).
GetLine: PROC [stream: STREAM, line: Line ¬ NIL] RETURNS [Line];
Return the next line from the stream. Use line if non-NIL.
GetDataLine: PROC [stream: STREAM, line: Line ¬ NIL] RETURNS [Line];
Return the next dataLine. Use line if non-NIL.
GetWord: PROC [line: Line] RETURNS [ROPE];
Return the next whitespace-delimited word in line, advancing the line index by one word.
GetInteger: PROC [line: Line] RETURNS [INTEGER];
Convert the next word in line to an integer and advance the line index accordingly.
GetReal: PROC [line: Line] RETURNS [REAL];
Convert the next word in line to a real and advance the line index accordingly.
GetPair: PROC [line: Line] RETURNS [Pair];
Convert the next two words in line to a pair and advance the line index accordingly.
GetTriple: PROC [line: Line] RETURNS [Triple];
Convert the next three words in line to a triple and advance the line index accordingly.
GetNats: PROC [line: Line] RETURNS [nats: NatSequence];
Convert the remainder of the line into a sequence of nats.
Read Procedures
The following read procedures leave the stream pointer at the end of the data read. All
searches for a keyWord begin at the current file position. If circularSearch is TRUE, the search
will, upon reaching end of file, resume at the file beginning and stop at the current position.
ReadRope: PROC [stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE]
RETURNS [ROPE];
Return remainder of the key line after the keyWord.
ReadInteger: PROC [stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE]
RETURNS [INTEGER];
Return integer after the key line.
ReadReal: PROC [stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE]
RETURNS [REAL];
Return real after the key line.
ReadPair: PROC [stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE]
RETURNS [Pair];
Return pair after the key line.
ReadTriple: PROC [stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE]
RETURNS [Triple];
Return triple after the key line.
The remaining Read procedures take an optional argument, nElements. If nElements is left
defaulted to zero, then the read procedure will attempt to convert all lines past the keyWord
line until a new keyWord line or comment line is found. The number of such lines is first
determined by reading ahead in the file. This can be time consuming for large files. If the
client knows the number of such lines, however, this look-ahead can be eliminated by
supplying a positive value for nElements.
ReadIntegerSequence: PROC [
stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE, nElements: INT ¬ 0]
RETURNS [IntegerSequence];
ReadRealSequence: PROC [
stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE, nElements: INT ¬ 0]
RETURNS [RealSequence];
If key non-nil, search file forward from current stream position for the key; if not found,
search file from its beginning.
ReadPairSequence: PROC [
stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE, nElements: INT ¬ 0]
RETURNS [PairSequence];
ReadTripleSequence: PROC [
stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE, nElements: INT ¬ 0]
RETURNS [TripleSequence];
ReadSurfaceSequence: PROC [
stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE, nElements: INT ¬ 0]
RETURNS [SurfaceSequence];
ReadFields: PROC [
stream: STREAM, keyWord: ROPE, circularSearch: BOOL ¬ FALSE, nElements: INT ¬ 0]
RETURNS [FieldSequence];
Read a sequence of lines from the file, beginning after the keyWord.
For example, suppose a file contains the key line:
Polygons~ index: Integer color: Triple vertices: Nats
followed by a set of lines, each containing a polygon index (integer), a color (triple) and a
sequence of vertex indices (nats). The information could be read from the file as follows:
indices: IntegerSequence;
colors: TripleSequence;
vertices: SurfaceSequence;
polygons: FieldSequence ← IO3d.ReadFields[stream, "Polygons"];
FOR n: NAT IN [0..fields.length) DO
SELECT TRUE FROM
Rope.Equal[polygons[n].id, "index"] => indices ← NARROW[polygons[n].sequence];
Rope.Equal[polygons[n].id, "color"] => colors ← NARROW[polygons[n].sequence];
Rope.Equal[polygons[n].id, "vertices"] => vertices ← NARROW[polygons[n].sequence];
ENDCASE => NULL;
ENDLOOP;
If one wished, for example, to print the vertices of the second polygon:
IF polygons.length > 1 THEN {
FOR n: NAT IN [0..vertices[1].length) DO
Print[vertices[1][n]];
ENDLOOP;
};
ReadMatrix: PROC [stream: STREAM] RETURNS [Matrix];
Write Procedures
WritePair: PROC [stream: STREAM, p: Pair];
Write the pair to the given stream.
WriteTriple: PROC [stream: STREAM, t: Triple];
Write the triple to the given stream.
WriteJustified: PROC [stream: STREAM, r: REAL];
Write the real to the given stream; if r >= 0, then justify with a space.
WriteFields: PROC [stream: STREAM, keyWord: ROPE, fields: FieldSequence];
Write the fields to the stream given the keyWord.
WriteMatrix: PROC [stream: STREAM, m: Matrix];
Write the matrix to the given stream.
Points/Polys Procedures
ReadPointsPolygons: PROC [fileName: ROPE]
RETURNS [points: TripleSequence, polygons: SurfaceSequence, errorMessage: ROPE];
Read points, polygons from a file.
If an error is encounted, points and polygons will be set to NIL.
The file is presumed to contain two lists:
a points list of triples preceded by the header, "~Points"
a polygon list of natSequences preceded by the header, "~Polygons"
WritePointsPolygons: PROC [fileName: ROPE, points: TripleSequence, polygons: SurfaceSequence];
Write points, polygons to a file.
Printing Procedures
PrintPair: PROC [stream: STREAM, pair: Pair, name: ROPE ¬ NIL];
print the value of pair on the given stream, optionally preceded by name.
PrintTriple: PROC [stream: STREAM, triple: Triple, name: ROPE ¬ NIL];
print the value of triple on the given stream, optionally preceded by name.
PrintQuad: PROC [stream: STREAM, quad: Quad, name: ROPE ¬ NIL];
print the value of quad on the given stream, optionally preceded by name.
PrintMatrix: PROC [stream: STREAM, matrix: Matrix, name: ROPE ¬ NIL];
print the value of matrix on the given stream, optionally preceded by name.
TiogaAccess
WriteCreate: PROC [title: ROPE] RETURNS [Writer];
Create the file.
WriteNode: PROC [
w: Writer,
node: ROPE,
looks: ROPE ¬ NIL,
comment: BOOL ¬ FALSE,
format: ATOM ¬ NIL];
Write entire node with the given looks and format.
WritePartialNode: PROC [w: Writer, node: ROPE, looks: ROPE ¬ NIL, comment: BOOL ¬ FALSE];
Add to the current node.
WriteKey: PROC [w: Writer, key: ROPE, val1, val2, val3: IO.Value ¬ [null[]]];
Add to the current node the key, in bold, and the value.
WriteNodeEnd: PROC [w: Writer];
Add end of node to current node.
END.