(* SimpCompReader.sml Seth Porter A rather brain-dead parser to read triangle patches and create a bool complex from them; currently only reads Garland's .SMF format. *) functor SMFReader3d(structure Complex : SIMPLICIAL_COMPLEX where type Vertex.point = RealGeometry3d.Point.point) : SIMP_COMP_READER where Complex=Complex = struct (* Import (currently a limited version) of Garland's SMF file format So far only supports "core operators" -- v x y z and f v1 v2 v3 when vertices strictly precede faces Very crude, too. *) structure Table = IntTable structure Complex = Complex structure Simplex = Complex.Simplex structure Vertex = Complex.Vertex structure Point = RealGeometry3d.Point exception BadNum exception BadVertex fun read(filename : string, init_fun) = let val infile = TextIO.openIn filename fun token_break #" " = true | token_break #"\t" = true | token_break _ = false fun parse_v(line, (vertices, v_num, complex)) = let fun real_strip s = case Real.fromString s of SOME(r) => r | NONE => raise BadNum val text_coords = List.tl(String.tokens token_break line) val coords = List.map real_strip text_coords val v = Vertex.new(Point.fromSeq(Sequence.fromList coords)) in (Table.insert((v_num, v), vertices), v_num+1, complex) end fun parse_f(line, (vertices, v_num, complex)) = let fun int_strip s = case Int.fromString s of NONE => raise BadNum | SOME(i) => i fun get_v v = case Table.find(v, vertices) of NONE => raise BadVertex | SOME(v') => v' val faces_text = List.tl(String.tokens token_break line) val vert_nums = List.map int_strip faces_text val verts = List.map get_v vert_nums val simplex = Simplex.fromSeq(Sequence.fromList verts) val complex' = case (init_fun simplex) of NONE => Complex.add(complex, simplex) | SOME(d) => Complex.addWithData(complex, simplex, SOME(d)) in (vertices, v_num, complex') end fun read_line(infile, state) = let val line = TextIO.inputLine infile in if line = "" then state else if String.isPrefix "#" line then read_line(infile, state) (* although not documented, he seems to use 'f' and 't' interchangeably *) else if String.isPrefix "f" line orelse String.isPrefix "t" line then read_line(infile, parse_f(line, state)) else if String.isPrefix "v" line then read_line(infile, parse_v(line, state)) else read_line(infile, state) end val (vertices, num_vertices, complex) = read_line(infile, (Table.empty, 1, Complex.new 2)) in TextIO.closeIn infile; (* (complex, num_vertices-1, vertices) *) complex end end