mesh2flac3d 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ """
2
+ mesh2flac3d — Export meshes (Gmsh .msh, VTK, ...) to Itasca FLAC3D .f3grid,
3
+ preserving physical groups as zone groups (ZGROUP) and boundary/face groups
4
+ as face groups (FGROUP), with guaranteed right-handed (positive-volume) zones.
5
+
6
+ Reads via `meshio` (any format it supports); writes a correct FLAC3D grid.
7
+ Does NOT import `gmsh`, so it carries no GPL obligation.
8
+
9
+ Basic use:
10
+
11
+ import mesh2flac3d as m2f
12
+ m2f.convert("model.msh", "model.f3grid")
13
+
14
+ Copyright (c) 2026 AI SIM Engenharia Geotecnica. MIT License.
15
+ """
16
+
17
+ from .core import convert, write_f3grid, Grid, __version__
18
+
19
+ __all__ = ["convert", "write_f3grid", "Grid", "__version__"]
mesh2flac3d/cli.py ADDED
@@ -0,0 +1,67 @@
1
+ """Command-line interface: ``mesh2flac3d input.msh output.f3grid``."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import sys
7
+
8
+ from .core import convert, __version__
9
+
10
+
11
+ def build_parser():
12
+ p = argparse.ArgumentParser(
13
+ prog="mesh2flac3d",
14
+ description="Convert a mesh (Gmsh .msh, VTK, ...) to FLAC3D .f3grid, "
15
+ "preserving physical groups as ZGROUP/FGROUP.",
16
+ )
17
+ p.add_argument("input", help="input mesh (e.g. model.msh)")
18
+ p.add_argument("output", nargs="?", help="output .f3grid (default: input with .f3grid)")
19
+ p.add_argument("--no-faces", action="store_true",
20
+ help="do not export 2D physical groups as faces/FGROUP")
21
+ p.add_argument("--float-fmt", default=".10e", help="coordinate format (default: .10e)")
22
+ p.add_argument("--slot", default="Default", help="FLAC3D group slot name")
23
+ p.add_argument("--input-format", default=None,
24
+ help="force meshio input format instead of inferring")
25
+ p.add_argument("--dat", metavar="FILE", default=None,
26
+ help="also write a FLAC3D command-file skeleton (.dat)")
27
+ p.add_argument("-q", "--quiet", action="store_true", help="suppress summary")
28
+ p.add_argument("--version", action="version", version=f"mesh2flac3d {__version__}")
29
+ return p
30
+
31
+
32
+ def main(argv=None):
33
+ args = build_parser().parse_args(argv)
34
+ output = args.output
35
+ if output is None:
36
+ output = args.input.rsplit(".", 1)[0] + ".f3grid"
37
+
38
+ grid = convert(
39
+ args.input, output,
40
+ keep_faces=not args.no_faces,
41
+ float_fmt=args.float_fmt,
42
+ slot=args.slot,
43
+ input_format=args.input_format,
44
+ )
45
+
46
+ if args.dat:
47
+ from .dat import write_dat_skeleton
48
+ write_dat_skeleton(args.dat, output, grid)
49
+
50
+ if not args.quiet:
51
+ nz = sum(len(c[1]) for c in grid.zone_cells)
52
+ nf = sum(len(c[1]) for c in grid.face_cells)
53
+ print(f"[mesh2flac3d] {args.input} -> {output}")
54
+ print(f" points: {len(grid.points)} zones: {nz} faces: {nf}")
55
+ if grid.zone_groups:
56
+ print(" zone groups: " + ", ".join(
57
+ f"{k}({len(v)})" for k, v in grid.zone_groups.items()))
58
+ if grid.face_groups:
59
+ print(" face groups: " + ", ".join(
60
+ f"{k}({len(v)})" for k, v in grid.face_groups.items()))
61
+ if args.dat:
62
+ print(f" command skeleton: {args.dat}")
63
+ return 0
64
+
65
+
66
+ if __name__ == "__main__":
67
+ sys.exit(main())
mesh2flac3d/core.py ADDED
@@ -0,0 +1,248 @@
1
+ """Core conversion logic: meshio Mesh -> FLAC3D .f3grid.
2
+
3
+ The FLAC3D grid (.f3grid) ASCII format used here:
4
+
5
+ * GRIDPOINTS
6
+ G <gid> <x> <y> <z>
7
+ * ZONES
8
+ Z <T4|W6|P5|B8> <zid> <n1> <n2> ...
9
+ * ZONE GROUPS
10
+ ZGROUP "<name>" SLOT <slot>
11
+ <zid> <zid> ...
12
+ * FACES
13
+ F <T3|Q4> <fid> <n1> <n2> ...
14
+ * FACE GROUPS
15
+ FGROUP "<name>" SLOT <slot>
16
+ <fid> <fid> ...
17
+
18
+ Node/zone/face IDs are 1-based. Zones and faces have independent ID spaces.
19
+ Zone connectivity is reordered so the first four corner nodes form a
20
+ right-handed system (positive volume) — FLAC3D rejects inverted zones.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import numpy as np
26
+
27
+ __version__ = "0.1.0"
28
+
29
+ # meshio cell type -> FLAC3D keyword
30
+ MESHIO_TO_FLAC3D_TYPE = {
31
+ "tetra": "T4",
32
+ "pyramid": "P5",
33
+ "wedge": "W6",
34
+ "hexahedron": "B8",
35
+ "triangle": "T3",
36
+ "quad": "Q4",
37
+ }
38
+
39
+ # 3D (zone) vs 2D (face) meshio types, mapping any high-order variant to its
40
+ # linear corner topology (we export corner nodes only).
41
+ ZONE_TYPES = {
42
+ "tetra": "tetra", "tetra10": "tetra",
43
+ "pyramid": "pyramid", "pyramid13": "pyramid",
44
+ "wedge": "wedge", "wedge12": "wedge", "wedge15": "wedge", "wedge18": "wedge",
45
+ "hexahedron": "hexahedron", "hexahedron20": "hexahedron",
46
+ "hexahedron24": "hexahedron", "hexahedron27": "hexahedron",
47
+ }
48
+ FACE_TYPES = {
49
+ "triangle": "triangle", "triangle6": "triangle", "triangle7": "triangle",
50
+ "quad": "quad", "quad8": "quad", "quad9": "quad",
51
+ }
52
+
53
+ # Node reordering meshio -> FLAC3D, and the mirror ordering used when the first
54
+ # variant yields a left-handed (negative) zone.
55
+ ORDER = {
56
+ "tetra": [0, 1, 2, 3],
57
+ "pyramid": [0, 1, 3, 4, 2],
58
+ "wedge": [0, 1, 3, 2, 4, 5],
59
+ "hexahedron": [0, 1, 3, 4, 2, 7, 5, 6],
60
+ }
61
+ ORDER_MIRROR = {
62
+ "tetra": [0, 2, 1, 3],
63
+ "pyramid": [0, 3, 1, 4, 2],
64
+ "wedge": [0, 2, 3, 1, 5, 4],
65
+ "hexahedron": [0, 3, 1, 4, 2, 5, 7, 6],
66
+ }
67
+
68
+ # cell_set keys produced by meshio readers that are not real physical groups.
69
+ _INTERNAL_SET_PREFIXES = ("gmsh:", "medit:", "cell_set-")
70
+
71
+
72
+ def _is_internal_key(key: str) -> bool:
73
+ return any(key.startswith(p) for p in _INTERNAL_SET_PREFIXES)
74
+
75
+
76
+ def _reorder_zone(points, conn, key):
77
+ """Reorder one block of zone connectivity to right-handed FLAC3D order.
78
+
79
+ `conn` is (n, k) corner indices into `points`; `key` is the linear type.
80
+ FLAC3D requires each zone to have positive volume: the first four corner
81
+ nodes must form a right-handed system, i.e. the scalar triple product
82
+ (p1-p0)x(p2-p0)-(p3-p0) > 0. (Verified against FLAC3D 7.0, which rejects a
83
+ grid with "tet volumes are <= 0" otherwise.) Returns (n, k) reordered so
84
+ every zone imports without a negative-volume error.
85
+ """
86
+ o1 = ORDER[key]
87
+ o2 = ORDER_MIRROR[key]
88
+ reordered = conn[:, o1]
89
+ p = points[reordered[:, :4]]
90
+ a = p[:, 1] - p[:, 0]
91
+ b = p[:, 2] - p[:, 0]
92
+ c = p[:, 3] - p[:, 0]
93
+ det = np.einsum("ij,ij->i", np.cross(a, b), c)
94
+ # keep o1 where it already yields positive volume (det > 0); else mirror it
95
+ out = np.where((det > 0)[:, None], conn[:, o1], conn[:, o2])
96
+ return out
97
+
98
+
99
+ class Grid:
100
+ """A FLAC3D grid ready to be written.
101
+
102
+ Built from a meshio Mesh. Splits cells into zones (3D) and faces (2D),
103
+ fixes zone winding, and resolves physical groups into zone/face groups
104
+ keyed by name.
105
+ """
106
+
107
+ def __init__(self, points, zone_cells, face_cells, zone_groups, face_groups):
108
+ self.points = points # (npts, 3) float
109
+ self.zone_cells = zone_cells # list of (flac3d_type, (n,k) int, base_id)
110
+ self.face_cells = face_cells # list of (flac3d_type, (n,k) int, base_id)
111
+ self.zone_groups = zone_groups # {name: np.array of 1-based zone ids}
112
+ self.face_groups = face_groups # {name: np.array of 1-based face ids}
113
+
114
+ @classmethod
115
+ def from_meshio(cls, mesh, keep_faces=True):
116
+ points = np.asarray(mesh.points, dtype=float)
117
+ if points.shape[1] == 2: # promote 2D coords to 3D
118
+ points = np.column_stack([points, np.zeros(len(points))])
119
+
120
+ # Assign global 1-based ids per block; map block index -> id offset.
121
+ zone_cells, face_cells = [], []
122
+ zone_block_base = {} # block_index -> first zone id (1-based)
123
+ face_block_base = {}
124
+ zid = 0
125
+ fid = 0
126
+ for bi, cb in enumerate(mesh.cells):
127
+ ct = cb.type
128
+ data = np.asarray(cb.data)
129
+ if ct in ZONE_TYPES:
130
+ key = ZONE_TYPES[ct]
131
+ corners = data[:, : len(ORDER[key])]
132
+ conn = _reorder_zone(points, corners, key)
133
+ zone_block_base[bi] = zid + 1
134
+ zone_cells.append((MESHIO_TO_FLAC3D_TYPE[key], conn, zid + 1))
135
+ zid += len(conn)
136
+ elif keep_faces and ct in FACE_TYPES:
137
+ key = FACE_TYPES[ct]
138
+ ncorner = 3 if key == "triangle" else 4
139
+ conn = data[:, :ncorner]
140
+ face_block_base[bi] = fid + 1
141
+ face_cells.append((MESHIO_TO_FLAC3D_TYPE[key], conn, fid + 1))
142
+ fid += len(conn)
143
+
144
+ zone_groups = cls._resolve_groups(mesh, zone_block_base, ZONE_TYPES)
145
+ face_groups = (
146
+ cls._resolve_groups(mesh, face_block_base, FACE_TYPES)
147
+ if keep_faces else {}
148
+ )
149
+ return cls(points, zone_cells, face_cells, zone_groups, face_groups)
150
+
151
+ @staticmethod
152
+ def _resolve_groups(mesh, block_base, type_filter):
153
+ """Turn meshio cell_sets into {name: 1-based global ids} for the given
154
+ cell family (zone or face). Falls back to cell_data gmsh:physical if no
155
+ named cell_sets exist."""
156
+ groups = {}
157
+ cell_sets = getattr(mesh, "cell_sets", None) or {}
158
+ for name, per_block in cell_sets.items():
159
+ if _is_internal_key(name):
160
+ continue
161
+ ids = []
162
+ for bi, local in enumerate(per_block):
163
+ if bi not in block_base or local is None:
164
+ continue
165
+ local = np.asarray(local)
166
+ if local.size == 0:
167
+ continue
168
+ ids.append(local + block_base[bi])
169
+ if ids:
170
+ groups[name] = np.unique(np.concatenate(ids))
171
+ return groups
172
+
173
+
174
+ def _write_table(f, ids, per_line=10):
175
+ ids = np.asarray(ids, dtype=int)
176
+ for i in range(0, len(ids), per_line):
177
+ f.write(" " + " ".join(str(v) for v in ids[i : i + per_line]) + "\n")
178
+
179
+
180
+ def write_f3grid(grid: Grid, path, float_fmt=".10e", slot="Default"):
181
+ """Write a Grid to a FLAC3D .f3grid ASCII file."""
182
+ with open(path, "w", encoding="utf-8") as f:
183
+ f.write(f"* FLAC3D grid produced by mesh2flac3d {__version__}\n")
184
+
185
+ f.write("* GRIDPOINTS\n")
186
+ fmt = "G {:d} " + " ".join(["{:" + float_fmt + "}"] * 3) + "\n"
187
+ for i, (x, y, z) in enumerate(grid.points, start=1):
188
+ f.write(fmt.format(i, x, y, z))
189
+
190
+ f.write("* ZONES\n")
191
+ for ftype, conn, base in grid.zone_cells:
192
+ for j, row in enumerate(conn):
193
+ zid = base + j
194
+ nodes = " ".join(str(int(v) + 1) for v in row)
195
+ f.write(f"Z {ftype} {zid} {nodes}\n")
196
+
197
+ if grid.zone_groups:
198
+ f.write("* ZONE GROUPS\n")
199
+ for name, ids in grid.zone_groups.items():
200
+ f.write(f'ZGROUP "{name}" SLOT "{slot}"\n')
201
+ _write_table(f, ids)
202
+
203
+ if grid.face_cells:
204
+ f.write("* FACES\n")
205
+ for ftype, conn, base in grid.face_cells:
206
+ for j, row in enumerate(conn):
207
+ fid = base + j
208
+ nodes = " ".join(str(int(v) + 1) for v in row)
209
+ f.write(f"F {ftype} {fid} {nodes}\n")
210
+
211
+ if grid.face_groups:
212
+ f.write("* FACE GROUPS\n")
213
+ for name, ids in grid.face_groups.items():
214
+ f.write(f'FGROUP "{name}" SLOT "{slot}"\n')
215
+ _write_table(f, ids)
216
+
217
+
218
+ def convert(input_path, output_path, keep_faces=True, float_fmt=".10e",
219
+ slot="Default", input_format=None):
220
+ """Read a mesh (any meshio-supported format) and write a FLAC3D .f3grid.
221
+
222
+ Parameters
223
+ ----------
224
+ input_path : str
225
+ Source mesh (e.g. Gmsh ``.msh``). Physical volume groups become zone
226
+ groups; physical surface groups become face groups.
227
+ output_path : str
228
+ Destination ``.f3grid``.
229
+ keep_faces : bool
230
+ Export 2D physical groups as FLAC3D faces/FGROUP (for boundary
231
+ conditions). Set False to export zones only.
232
+ float_fmt : str
233
+ Coordinate format spec.
234
+ slot : str
235
+ FLAC3D group slot name.
236
+ input_format : str, optional
237
+ Force a meshio input format instead of inferring from the extension.
238
+
239
+ Returns
240
+ -------
241
+ Grid
242
+ """
243
+ import meshio # imported lazily; meshio is MIT-licensed
244
+
245
+ mesh = meshio.read(input_path, file_format=input_format)
246
+ grid = Grid.from_meshio(mesh, keep_faces=keep_faces)
247
+ write_f3grid(grid, output_path, float_fmt=float_fmt, slot=slot)
248
+ return grid
mesh2flac3d/dat.py ADDED
@@ -0,0 +1,40 @@
1
+ """Optional FLAC3D command-file (.dat) skeleton generator.
2
+
3
+ Emits a *generic* starting script that imports the grid and stubs out a
4
+ constitutive model assignment per zone group and a boundary condition per face
5
+ group. It contains no project-specific parameters — the user fills those in.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import os
11
+
12
+
13
+ def write_dat_skeleton(path, f3grid_path, grid):
14
+ grid_name = os.path.basename(f3grid_path)
15
+ with open(path, "w", encoding="utf-8") as f:
16
+ f.write("; FLAC3D command skeleton generated by mesh2flac3d\n")
17
+ f.write("; Fill in constitutive models, properties and BC values.\n\n")
18
+ f.write("model new\n")
19
+ f.write("model large-strain off\n")
20
+ f.write(f"zone import '{grid_name}'\n\n")
21
+
22
+ f.write("; --- Constitutive model per zone group ---\n")
23
+ if grid.zone_groups:
24
+ for name in grid.zone_groups:
25
+ f.write(f"zone cmodel assign elastic range group '{name}'\n")
26
+ f.write(f"; zone property young 1e9 poisson 0.3 range group '{name}'\n")
27
+ else:
28
+ f.write("; (no zone groups found)\n")
29
+ f.write("\n")
30
+
31
+ f.write("; --- Boundary conditions per face group ---\n")
32
+ if grid.face_groups:
33
+ for name in grid.face_groups:
34
+ f.write(f"; zone face apply velocity-normal 0 range group '{name}'\n")
35
+ else:
36
+ f.write("; (no face groups found)\n")
37
+ f.write("\n")
38
+
39
+ f.write("; model gravity 0 0 -9.81\n")
40
+ f.write("; model solve\n")
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: mesh2flac3d
3
+ Version: 0.1.0
4
+ Summary: Convert Gmsh/VTK meshes to Itasca FLAC3D .f3grid, preserving physical groups (ZGROUP/FGROUP) with correct zone winding.
5
+ Author: AI SIM Engenharia Geotecnica
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Jeanbjoseph/mesh2flac3d
8
+ Project-URL: Issues, https://github.com/Jeanbjoseph/mesh2flac3d/issues
9
+ Keywords: flac3d,gmsh,mesh,geomechanics,itasca,f3grid,finite-element
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Topic :: Scientific/Engineering
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: meshio>=5
18
+ Requires-Dist: numpy>=1.20
19
+ Provides-Extra: test
20
+ Requires-Dist: pytest>=7; extra == "test"
21
+ Requires-Dist: gmsh>=4; extra == "test"
22
+ Dynamic: license-file
23
+
24
+ # mesh2flac3d
25
+
26
+ [![CI](https://github.com/Jeanbjoseph/mesh2flac3d/actions/workflows/ci.yml/badge.svg)](https://github.com/Jeanbjoseph/mesh2flac3d/actions/workflows/ci.yml)
27
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
28
+
29
+ Convert meshes (Gmsh `.msh`, VTK, and anything [meshio](https://github.com/nschloe/meshio) reads) to **Itasca FLAC3D** `.f3grid` grids — **preserving physical groups**:
30
+
31
+ - **Volume** physical groups → **`ZGROUP`** (zone groups)
32
+ - **Surface** physical groups → **`FGROUP`** (face groups, for boundary conditions)
33
+ - **Correct zone winding**: every zone is reordered to FLAC3D's convention, so you never get *negative-volume zone* errors on import.
34
+
35
+ It reads meshes through `meshio` (MIT) and **does not import `gmsh`**, so it carries no GPL obligation — you can use it freely, including in commercial workflows.
36
+
37
+ ## Why not just use meshio?
38
+
39
+ `meshio` has a FLAC3D writer, but for a typical geomechanics mesh (volume **and** surface physical groups) it currently:
40
+
41
+ - **crashes** (`TypeError` in `split_f_z`) when both zone and face groups are present, and
42
+ - **drops all 2D groups** (`"FLAC3D format only supports 3D cells. Skipping triangle…"`), so you lose the face groups you need for boundary conditions, and
43
+ - does not guarantee zone orientation.
44
+
45
+ `mesh2flac3d` is a focused, correct writer built for that exact case.
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ pip install mesh2flac3d # once published
51
+ # or, from source:
52
+ pip install -e .
53
+ ```
54
+
55
+ ## Command line
56
+
57
+ ```bash
58
+ mesh2flac3d model.msh model.f3grid
59
+ mesh2flac3d model.msh # -> model.f3grid
60
+ mesh2flac3d model.msh out.f3grid --dat out.dat # also write a FLAC3D command skeleton
61
+ mesh2flac3d model.msh --no-faces # zones only
62
+ ```
63
+
64
+ Example output:
65
+
66
+ ```
67
+ [mesh2flac3d] model.msh -> model.f3grid
68
+ points: 350 zones: 1218 faces: 522
69
+ zone groups: Underburden(401), Salt(414), Overburden(403)
70
+ face groups: Top(90), Bottom(90), Sides(342)
71
+ ```
72
+
73
+ ## Python API
74
+
75
+ ```python
76
+ import mesh2flac3d as m2f
77
+
78
+ grid = m2f.convert("model.msh", "model.f3grid")
79
+ print(grid.zone_groups.keys()) # dict_keys(['Underburden', 'Salt', 'Overburden'])
80
+ print(grid.face_groups.keys()) # dict_keys(['Top', 'Bottom', 'Sides'])
81
+ ```
82
+
83
+ ## Supported elements
84
+
85
+ | Family | Gmsh / meshio | FLAC3D |
86
+ |--------|------------------------|--------|
87
+ | Zones | tetra | T4 |
88
+ | | pyramid | P5 |
89
+ | | wedge / prism | W6 |
90
+ | | hexahedron | B8 |
91
+ | Faces | triangle | T3 |
92
+ | | quad | Q4 |
93
+
94
+ High-order variants (tetra10, hexahedron20, …) are exported using their linear
95
+ corner nodes.
96
+
97
+ ## In Gmsh, name your groups
98
+
99
+ Give your regions and boundaries **Physical Groups** with names — those names
100
+ become the FLAC3D group names:
101
+
102
+ ```
103
+ Physical Volume("Salt") = {2};
104
+ Physical Surface("Top") = {4};
105
+ ```
106
+
107
+ ## Development
108
+
109
+ ```bash
110
+ pip install -e ".[test]"
111
+ pytest -q
112
+ ```
113
+
114
+ The test fixture is generated with Gmsh (`tests/fixtures/make_testmesh.py`);
115
+ Gmsh is a **test-only** dependency, never used by the package at runtime.
116
+
117
+ ## License
118
+
119
+ MIT © AI SIM Engenharia Geotécnica. FLAC3D and Itasca are trademarks of Itasca
120
+ Consulting Group; this project is independent and not affiliated with Itasca.
@@ -0,0 +1,10 @@
1
+ mesh2flac3d/__init__.py,sha256=8CCQYJ_M4ZVcy3nVw1PSbI0gUd3Risk8KGWb1wCD0ZA,647
2
+ mesh2flac3d/cli.py,sha256=4Ry4kXDYgi6H-VQrr3tpFnv599khuOYLro5hSYfI69I,2472
3
+ mesh2flac3d/core.py,sha256=pQQ1BdRepm0u_1WFTEKrw9SZfy-RtW7pf9c1R16l-cU,9110
4
+ mesh2flac3d/dat.py,sha256=82AvV6qhhKEP3GQkQG1WQ6V0RPMCHcddKhH-jM15aeM,1548
5
+ mesh2flac3d-0.1.0.dist-info/licenses/LICENSE,sha256=TF3LBXkec1FJ1k8HniHBuFOPQM_03pbmE_RScq1fCeQ,1085
6
+ mesh2flac3d-0.1.0.dist-info/METADATA,sha256=tCDCUfzYWQYlNC2qptLXbWqxjt2QgZUoKRHj2VAA0zk,4322
7
+ mesh2flac3d-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
8
+ mesh2flac3d-0.1.0.dist-info/entry_points.txt,sha256=L7rFUmbOwaANdYRCEZRPit_Nhc8JqXTfYOlxrMwSIzM,53
9
+ mesh2flac3d-0.1.0.dist-info/top_level.txt,sha256=MVEVbn8wswTsmbRMEu_Q4zcHKP4Qwolen120U0YQyDk,12
10
+ mesh2flac3d-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mesh2flac3d = mesh2flac3d.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AI SIM Engenharia Geotecnica
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ mesh2flac3d