nschloe/meshio

[BUG] Error: could not read file containing a valid empty WKT TIN string

swiss-knight opened this issue · 2 comments

Hello,

I'm facing troubles when trying to load a text file containing an empty, yet valid TIN as a WKT string using meshio==5.3.4 in Python 3.10.6 on Ubuntu 22.04.1 LTS.

Everything works fine for files containing data, but empty TIN strings seem to issue an error.
The WKT string in such file is as follow:

$ cat /home/username/TINS/tin_empty_1234.wkt
TIN EMPTY

(it may also be: TIN Z EMPTY)

Both are valid PostGIS 3.3+ format:

SELECT ST_IsValid(ST_GeomFromText('TIN Z EMPTY'));
 st_isvalid 
------------
 t
(1 row)

SELECT ST_IsValid(ST_GeomFromText('TIN Z EMPTY'));
 st_isvalid 
------------
 t
(1 row)

-- an example with valid WKT
SELECT ST_IsValid(ST_GeomFromText('FOO EMPTY'));

  ERROR:  parse error - invalid geometry
  HINT:  "FO" <-- parse error at position 2 within geometry

This is a reminder on the current empty geometries in PostGIS, both in WKT and hex WKB:

database=# SELECT ST_AsText(geom), geom::text
FROM (
  SELECT i, (postgis_typmod_type(i) || ' EMPTY')::geometry AS geom
  FROM generate_series(4, 63) AS i) f
ORDER BY i;
          st_astext          |                                    geom                                    
-----------------------------+----------------------------------------------------------------------------
 POINT EMPTY                 | 0101000000000000000000F87F000000000000F87F
 POINT M EMPTY               | 0101000040000000000000F87F000000000000F87F000000000000F87F
 POINT Z EMPTY               | 0101000080000000000000F87F000000000000F87F000000000000F87F
 POINT ZM EMPTY              | 01010000C0000000000000F87F000000000000F87F000000000000F87F000000000000F87F
 LINESTRING EMPTY            | 010200000000000000
 LINESTRING M EMPTY          | 010200004000000000
 LINESTRING Z EMPTY          | 010200008000000000
 LINESTRING ZM EMPTY         | 01020000C000000000
 POLYGON EMPTY               | 010300000000000000
 POLYGON M EMPTY             | 010300004000000000
 POLYGON Z EMPTY             | 010300008000000000
 POLYGON ZM EMPTY            | 01030000C000000000
 MULTIPOINT EMPTY            | 010400000000000000
 MULTIPOINT M EMPTY          | 010400004000000000
 MULTIPOINT Z EMPTY          | 010400008000000000
 MULTIPOINT ZM EMPTY         | 01040000C000000000
 MULTILINESTRING EMPTY       | 010500000000000000
 MULTILINESTRING M EMPTY     | 010500004000000000
 MULTILINESTRING Z EMPTY     | 010500008000000000
 MULTILINESTRING ZM EMPTY    | 01050000C000000000
 MULTIPOLYGON EMPTY          | 010600000000000000
 MULTIPOLYGON M EMPTY        | 010600004000000000
 MULTIPOLYGON Z EMPTY        | 010600008000000000
 MULTIPOLYGON ZM EMPTY       | 01060000C000000000
 GEOMETRYCOLLECTION EMPTY    | 010700000000000000
 GEOMETRYCOLLECTION M EMPTY  | 010700004000000000
 GEOMETRYCOLLECTION Z EMPTY  | 010700008000000000
 GEOMETRYCOLLECTION ZM EMPTY | 01070000C000000000
 CIRCULARSTRING EMPTY        | 010800000000000000
 CIRCULARSTRING M EMPTY      | 010800004000000000
 CIRCULARSTRING Z EMPTY      | 010800008000000000
 CIRCULARSTRING ZM EMPTY     | 01080000C000000000
 COMPOUNDCURVE EMPTY         | 010900000000000000
 COMPOUNDCURVE M EMPTY       | 010900004000000000
 COMPOUNDCURVE Z EMPTY       | 010900008000000000
 COMPOUNDCURVE ZM EMPTY      | 01090000C000000000
 CURVEPOLYGON EMPTY          | 010A00000000000000
 CURVEPOLYGON M EMPTY        | 010A00004000000000
 CURVEPOLYGON Z EMPTY        | 010A00008000000000
 CURVEPOLYGON ZM EMPTY       | 010A0000C000000000
 MULTICURVE EMPTY            | 010B00000000000000
 MULTICURVE M EMPTY          | 010B00004000000000
 MULTICURVE Z EMPTY          | 010B00008000000000
 MULTICURVE ZM EMPTY         | 010B0000C000000000
 MULTISURFACE EMPTY          | 010C00000000000000
 MULTISURFACE M EMPTY        | 010C00004000000000
 MULTISURFACE Z EMPTY        | 010C00008000000000
 MULTISURFACE ZM EMPTY       | 010C0000C000000000
 POLYHEDRALSURFACE EMPTY     | 010F00000000000000
 POLYHEDRALSURFACE M EMPTY   | 010F00004000000000
 POLYHEDRALSURFACE Z EMPTY   | 010F00008000000000
 POLYHEDRALSURFACE ZM EMPTY  | 010F0000C000000000
 TRIANGLE EMPTY              | 011100000000000000
 TRIANGLE M EMPTY            | 011100004000000000
 TRIANGLE Z EMPTY            | 011100008000000000
 TRIANGLE ZM EMPTY           | 01110000C000000000
 TIN EMPTY                   | 011000000000000000
 TIN M EMPTY                 | 011000004000000000
 TIN Z EMPTY                 | 011000008000000000
 TIN ZM EMPTY                | 01100000C000000000
(60 rows)

and this is my current Traceback when I try to load the file containing an empty WKT TIN string:

#Python 3.10.6 (main, Nov  2 2022, 18:53:38) [GCC 11.3.0]

import meshio

filepath = '/home/username/TINS/tin_empty_1234.wkt'

with open(filepath) as f:
    meshio.read(filepath,'wkt')

which leads to:

Error: Couldn't read file /home/username/TINS/tin_empty_1234.wkt as 
wkt
Invalid WKT TIN
An exception has occurred, use %tb to see the full traceback.

SystemExit: 1

/usr/local/lib/python3.10/dist-packages/IPython/core/interactiveshell.py:3561: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)

and:

%tb
Traceback (most recent call last):

  File "/tmp/ipykernel_2680153/3790614806.py", line 2, in <cell line: 1>
    meshio.read(filepath,'wkt')

  File "/usr/local/lib/python3.10/dist-packages/meshio/_helpers.py", line 71, in read
    return _read_file(Path(filename), file_format)

  File "/usr/local/lib/python3.10/dist-packages/meshio/_helpers.py", line 114, in _read_file
    sys.exit(1)

SystemExit: 1

Could it be possible to consider empty, yet valid WKT TIN strings as well?

Many thanks for your help!
Warm Regards.

So it's this part of the code that throws the error:

tin_match = tin_re.match(s)
if tin_match is None:
raise ReadError("Invalid WKT TIN")

...which means that you'll need to change the tin_pattern regex (or maybe better, have a second regex option for empty wkt files)

tin_pattern = rf"TIN\s*\((?:\s*{triangle_pattern}\s*,?)*\s*\)"

Questions for you:

  1. Do you have a small example wkt file with data?
  2. Do you have a small example wkt file that is EMPTY?
  3. What do you want to happen when you read an empty wkt file in? What do you expect to see returned?

I'm confused about why you want to do this. meshio doesn't really have a concept of an empty mesh, but you can kind of hack an empty mesh like this: meshio.Mesh(np.array([]), np.array([])). Is that similar to what you wanted?