-- File: TFI3dImpl.mesa (text file in for 3d)
-- Last edited by Bier on July 6, 1983 4:28 pm
-- Contents: convenience functions for parsing low-level parts of a 3d fileout produced by fileout3d.mesa
DIRECTORY
GraphicsColor,
IO,
Matrix3d,
Rope,
SVArtwork,
SVVector3d,
SVMappings,
SVMatrix2d,
TFI3d;
TFI3dImpl: PROGRAM
IMPORTS GraphicsColor, IO, Matrix3d, SVArtwork, SVMappings, SVMatrix2d, Rope
EXPORTS TFI3d =
BEGIN
Color: TYPE = GraphicsColor.Color;
Matrix3by3: TYPE = SVMatrix2d.Matrix3by3;
Matrix4by4: TYPE = Matrix3d.Matrix4by4;
OMap: TYPE = SVArtwork.OMap;
Point3d: TYPE = Matrix3d.Point3d;
Point2d: TYPE = Matrix3d.Point2d;
Vector: TYPE = SVVector3d.Vector;
Material: TYPE = SVArtwork.Material;
SMap: TYPE = SVArtwork.SMap;
CharClass: TYPE = IO.CharClass;
-- {break, sepr, other}
FileinMatrix: PUBLIC PROC [f: IO.STREAM] RETURNS [mat: Matrix4by4] = {
mat ← Matrix3d.Identity[];
ReadRope[f, "["];
ReadBlankAndRope[f, "["];
mat[1][1] ← ReadBlankAndReal[f];
FOR j: NAT IN[2..4] DO
ReadBlankAndRope[f,","];
mat[1][j] ← ReadBlankAndReal[f];
ENDLOOP;
ReadBlank[f];
ReadBlankAndRope[f, "]"];
FOR i: NAT IN[2..3] DO
ReadBlankAndRope[f, ","];
ReadBlankAndRope[f, "["];
mat[i][1] ← ReadBlankAndReal[f];
FOR j: NAT IN[2..4] DO
ReadBlankAndRope[f, ","];
mat[i][j] ← ReadBlankAndReal[f];
ENDLOOP;
ReadBlankAndRope[f, "]"];
ENDLOOP;
ReadBlankAndRope[f, "]"];
}; -- end of FileinMatrix
FileinMatrix3by3: PUBLIC PROC [f: IO.STREAM] RETURNS [mat: Matrix3by3] = {
mat ← SVMatrix2d.Identity[];
ReadRope[f, "["];
ReadBlankAndRope[f, "["];
mat[1][1] ← ReadBlankAndReal[f];
FOR j: NAT IN[2..3] DO
ReadBlankAndRope[f,","];
mat[1][j] ← ReadBlankAndReal[f];
ENDLOOP;
ReadBlank[f];
ReadBlankAndRope[f, "]"];
ReadBlankAndRope[f, ","];
ReadBlankAndRope[f, "["];
mat[2][1] ← ReadBlankAndReal[f];
FOR j: NAT IN[2..3] DO
ReadBlankAndRope[f, ","];
mat[2][j] ← ReadBlankAndReal[f];
ENDLOOP;
ReadBlankAndRope[f, "]"];
ReadBlankAndRope[f, "]"];
}; -- end of FileinMatrix3by3
ReadRope: PUBLIC PROC [f: IO.STREAM, rope: Rope.ROPE] = {
-- removes the given rope from the top of the stream. Used to remove formatting words and phrases from 3d files. We are not interested in these strings but only in the data in between them.
-- Signals RopeNotOnTop if some other rope is on top.
c: CHAR;
FOR i: NAT IN[1..Rope.Length[rope]] DO
c ← IO.GetChar[f];
IF NOT c = Rope.Fetch[rope,i-1] THEN
SIGNAL RopeNotOnTop [IO.GetIndex[f], Rope.FromChar[c], rope];
ENDLOOP;
};
RopeNotOnTop: PUBLIC SIGNAL [position: NAT, wasThere: Rope.ROPE, notThere: Rope.ROPE] = CODE;
ReadChar: PUBLIC PROC [f: IO.STREAM, c: CHAR] = {
streamC: CHAR ← IO.GetChar[f];
IF NOT c = streamC THEN SIGNAL RopeNotOnTop[IO.GetIndex[f], Rope.FromChar[streamC], Rope.FromChar[c]];
};
ReadReturn: PUBLIC PROC [f: IO.STREAM] = {
-- convenience function. Equivalent to ReadChar[f, IO.CR];
ReadChar[f, IO.CR];
};
WordBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED {
SELECT char FROM
IO.TAB => RETURN [break];
IO.CR =>RETURN [break];
IO.SP => RETURN [break];
', => RETURN [break];
'] => RETURN [break];
') => RETURN [break];
ENDCASE => RETURN [other];
};
KeyWordBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED {
SELECT char FROM
IO.CR =>RETURN [break];
': => RETURN [break];
ENDCASE => RETURN [other];
};
ReadWord: PUBLIC PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = {
-- reads a rope until <SPACE>, <CR>, <COMMA> or <TAB> are encountered. Used to read in a rope which is data. ie the name of a coordinate system from a 3d file.
word ← IO.GetToken[f, WordBreakProc];
};
ReadKeyWord: PUBLIC PROC [f: IO.STREAM] RETURNS [keyWord: Rope.ROPE, good: BOOL] = {
-- reads a rope until a ':' or <CR> are encountered. If CR is encountered first, then good is FALSE since ":" is expected after a keyword.
nextChar: Rope.ROPE;
keyWord ← IO.GetToken[f, KeyWordBreakProc];
nextChar ← IO.GetToken[f, KeyWordBreakProc];
good ← Rope.Equal[nextChar, ":", TRUE];
};
LineBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED {
SELECT char FROM
IO.CR =>RETURN [break];
ENDCASE => RETURN [other];
};
ReadLine: PUBLIC PROC [f: IO.STREAM] RETURNS [line: Rope.ROPE] = {
-- reads a rope UNTIL <CR> is encountered. Used to read Solidviews version rope
line ← IO.GetToken[f, LineBreakProc];
[] ← IO.GetToken[f, LineBreakProc]; -- remove <CR>
};
WhiteSpaceProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED {
SELECT char FROM
IO.TAB => RETURN [other];
IO.CR =>RETURN [other];
IO.SP => RETURN [other];
ENDCASE => RETURN [break];
};
ReadWhiteSpace: PUBLIC PROC [f: IO.STREAM] = {
-- reads, <SPACE>'s, <CR>'s, and <TAB>'s until something else is encountered. Signals RopeNotOnTop if no white space characters are found.
whiteSpace: Rope.ROPE ← IO.GetToken[f, WhiteSpaceProc];
IF Rope.Size[whiteSpace] = 0 THEN SIGNAL RopeNotOnTop[IO.GetIndex[f], "null", "<whitespace>"];
};
ReadBlank: PUBLIC PROC [f: IO.STREAM] = {
-- reads, <SPACE>'s, <CR>'s, and <TAB>'s until something else is encountered. Doesn't mind if no white space characters are found.
whiteSpace: Rope.ROPE;
len: NAT;
c: CHAR;
whiteSpace ← IO.GetSequence[f, BlankProc];
len ← Rope.Size[whiteSpace];
IF len # 0 THEN {
c ← Rope.Fetch[whiteSpace, len-1];
IO.Backup[f, c];
RETURN;
};
};
BlankProc: SAFE PROC [char: CHAR] RETURNS [quit: BOOL ← FALSE, include: BOOL ← TRUE] = TRUSTED {
SELECT char FROM
IO.CR, IO.TAB, IO.SP => RETURN [FALSE, TRUE];
ENDCASE => RETURN [TRUE, TRUE];
};
ReadHorizontalBlank: PUBLIC PROC [f: IO.STREAM] RETURNS [good: BOOL] = {
-- reads <SPACE>'s, and <TABS>'s until something else is encountered. Returns good = FALSE if a CR is encountered before anything else
whiteSpace: Rope.ROPE;
len: NAT;
c: CHAR;
good ← TRUE;
whiteSpace ← IO.GetSequence[f, HorizontalBlankProc];
len ← Rope.Size[whiteSpace];
IF len # 0 THEN {
c ← Rope.Fetch[whiteSpace, len-1];
IF c = IO.CR THEN good ← FALSE;
IO.Backup[f, c];
RETURN;
};
};
HorizontalBlankProc: SAFE PROC [char: CHAR] RETURNS [quit: BOOL ← FALSE, include: BOOL ← TRUE] = TRUSTED {
SELECT char FROM
IO.TAB, IO.SP => RETURN [FALSE, TRUE];
ENDCASE => RETURN [TRUE, TRUE];
};
ReadBlankAndRope: PUBLIC PROC [f: IO.STREAM, rope: Rope.ROPE] = {
ReadBlank[f];
ReadRope[f, rope];
};
ReadBlankAndReal: PUBLIC PROC [f: IO.STREAM] RETURNS [r: REAL] = {
-- a convenience function. Equivalent to ReadBlank[f]; r ← ReadReal[f];
ReadBlank[f];
r ← ReadReal[f];
};
ReadBlankAndWord: PUBLIC PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = {
-- a convenience function. Equivalent to ReadBlank[f]; word ← ReadWord[f];
ReadBlank[f];
word ← ReadWord[f];
};
ReadBlankAndNAT: PUBLIC PROC [f: IO.STREAM] RETURNS [n: NAT] = {
-- a convenience function. Equivalent to ReadBlank[f]; n ← ReadNAT[f];
ReadBlank[f];
n ← ReadNAT[f];
};
ReadPoint3d: PUBLIC PROC [f: IO.STREAM] RETURNS [point3d: Point3d] = {
-- assumes the next rope on the stream will be of the form "[<real1>,<real2>,<real3>]".
ReadRope[f, "["];
point3d[1] ← ReadBlankAndReal[f];
ReadRope[f, ","];
point3d[2] ← ReadBlankAndReal[f];
ReadRope[f, ","];
point3d[3] ← ReadBlankAndReal[f];
ReadRope[f, "]"];
};
ReadPoint2d: PUBLIC PROC [f: IO.STREAM] RETURNS [point2d: Point2d] = {
-- assumes the next rope on the stream will be of the form "[<real1>,<real2>]".
ReadRope[f, "["];
point2d[1] ← ReadBlankAndReal[f];
ReadRope[f, ","];
point2d[2] ← ReadBlankAndReal[f];
ReadRope[f, "]"];
};
ReadPoint2dAsPoint3d: PUBLIC PROC [f: IO.STREAM] RETURNS [point3d: Point3d] = {
-- assumes the next rope on the stream will be of the form "[<real1>,<real2>]". Fills in point3d[3] with zero.
ReadRope[f, "["];
point3d[1] ← ReadBlankAndReal[f];
ReadRope[f, ","];
point3d[2] ← ReadBlankAndReal[f];
point3d[3] ← 0;
ReadRope[f, "]"];
};
RealBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED {
SELECT char FROM
'], ', => RETURN [break];
IO.CR =>RETURN [break];
IO.SP => RETURN [break];
ENDCASE => RETURN [other];
};
ReadReal: PUBLIC PROC [f: IO.STREAM] RETURNS [r: REAL] = {
-- reads digits up to the next ], <CR>, <SPACE> or <COMMA>. Leaves these terminators on the stream.
realRope: Rope.ROPE ← IO.GetToken[f, RealBreakProc];
IF Rope.Find[realRope, ".", 0, FALSE] = -1 THEN realRope ← Rope.Concat[realRope, ".0"];
r ← IO.GetReal[IO.RIS[realRope]];
};
NATBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED {
SELECT char FROM
'], IO.CR, IO.SP, '., ', => RETURN [break];
ENDCASE => RETURN [other];
};
ReadNAT: PUBLIC PROC [f: IO.STREAM] RETURNS [n: NAT] = {
-- reads digits up to the next ], <CR>, <SPACE>. Leaves these terminators on the stream.
intRope: Rope.ROPE ← IO.GetToken[f, NATBreakProc];
n ← IO.GetInt[IO.RIS[intRope]];
};
BoolBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED {
SELECT char FROM
'], IO.CR, IO.SP, '., ', => RETURN [break];
ENDCASE => RETURN [other];
};
ReadBool: PUBLIC PROC [f: IO.STREAM] RETURNS [truth: BOOL, good: BOOL] = {
-- tries to read TRUE or FALSE from the stream. If it encounters another word, good = FALSE;
boolRope: Rope.ROPE ← IO.GetToken[f, BoolBreakProc];
good ← TRUE;
IF Rope.Equal[boolRope, "TRUE", TRUE] THEN {
truth ← TRUE}
ELSE IF Rope.Equal[boolRope, "FALSE", TRUE] THEN {
truth ← FALSE}
ELSE {truth ← FALSE; good ← FALSE};
};
ReadColor: PUBLIC PROC [f: IO.STREAM] RETURNS [color: Color] = {
r, g, b: REAL;
ReadChar[f, '[];
r ← ReadBlankAndReal[f];
ReadChar[f, ',];
g ← ReadBlankAndReal[f];
ReadChar[f, ',];
b ← ReadBlankAndReal[f];
ReadChar[f, ']];
color ← GraphicsColor.RGBToColor[r, g, b];
}; -- end of ReadColor
ReadSurface: PUBLIC PROC [f: IO.STREAM] RETURNS [surface: REF ANY] = {
surfType: Rope.ROPE ← ReadBlankAndWord[f];
SELECT TRUE FROM
Rope.Equal[surfType, "tube", FALSE] => {
radius, height: REAL;
ReadBlankAndRope[f, "[radius:"];
radius ← ReadBlankAndReal[f];
ReadBlankAndRope[f, ","];
ReadBlankAndRope[f, "height:"];
height ← ReadBlankAndReal[f];
ReadBlankAndRope[f, "]"];
surface ← SVMappings.CreateTube[radius, height];
};
Rope.Equal[surfType, "box", FALSE] => {
boxSide: Vector;
ReadBlank[f];
boxSide ← ReadPoint3d[f];
surface ← SVMappings.CreateBox[boxSide[1], boxSide[2], boxSide[3]];
};
Rope.Equal[surfType, "NIL"] => {};
ENDCASE => ERROR;
}; -- end of ReadSurface
ReadMaterial: PUBLIC PROC [f: IO.STREAM] RETURNS [material: Material] = {
matRope: Rope.ROPE ← ReadWord[f];
success: BOOL;
[material, success] ← SVArtwork.RopeToMaterial[matRope];
IF NOT success THEN ERROR;
};
ReadSMap: PUBLIC PROC [f: IO.STREAM] RETURNS [sMap: SMap] = {
mapRope: Rope.ROPE ← ReadWord[f];
success: BOOL;
[sMap, success] ← SVArtwork.RopeToSMap[mapRope];
IF NOT success THEN ERROR;
};
ReadOMap: PUBLIC PROC [f: IO.STREAM] RETURNS [oMap: OMap] = {
mapRope: Rope.ROPE ← ReadWord[f];
success: BOOL;
[oMap, success] ← SVArtwork.RopeToOMap[mapRope];
IF NOT success THEN ERROR;
};
END.