Re: Parser stl et regexp

Top Page

Reply to this message
Author: Vincent Caron
Date:  
To: guilde Guilde
Subject: Re: Parser stl et regexp
On 21/03/2013 12:56, Frédéric wrote:
> Hello,
>
> Petite questions aux guru regexp...
>
> Je voudrais parser un fichier stl. En ascii, c'est de la forme :
>
>         solid _40x10
>             facet normal 0.000000e+000 0.000000e+000 1.000000e+000
>                 outer loop
>                     vertex 1.286803e+001 2.957990e+001 1.200000e+001
>                     vertex 1.173648e+001 2.984808e+001 1.200000e+001
>                     vertex 1.115715e+001 2.953001e+001 1.200000e+001
>                 endloop
>             endfacet
>             facet normal 0.000000e+000 0.000000e+000 1.000000e+000
>                 outer loop
>                     vertex 1.115715e+001 2.953001e+001 1.200000e+001
>                     vertex 1.173648e+001 2.984808e+001 1.200000e+001
>                     vertex 1.058145e+001 2.998308e+001 1.200000e+001
>                 endloop
>             endfacet
>             ...
>         endsolid _40x10

>
> Je voudrais pouvoir récupérer des groupes :
>
> - le(s) groupe(s) de lignes compris entre 'solid/endsolid'
> - le(s) groupe(s) de lignes compris entre 'facet/endfacet'
> - le(s) groupe(s) de lignes compris entre 'solid/endsolid'
> - le(s) groupe(s) de lignes compris entre 'outer loop/endloop'


Ca dépend comment tu récupères ces infos, suivant l'approche SAX ou
DOM. Ca se programme pas de la même façon.

Voici une solution pragmatique pour une approche DOM, qui suppose que
le document est bien formé (et donc ne traite pas du tout les balises
fermantes, et suppose une imbrication parfaitement régulière solid ->
facet -> loop -> vertex) :

#!/usr/bin/python

import sys
import re

stl = []

for rawline in sys.stdin:
    line = re.sub(r'^\s+', '', rawline)


    m = re.match(r'solid (.*)', line)
    if m:
        facets = []
        solid = {'id': m.group(1), 'facets': facets}
        stl.append(solid)


    m = re.match(r'facet normal (.*)', line)
    if m:
        loops = []
        facet = {'normal': m.group(1), 'loops' : loops}
        solid['facets'].append(facet)


    m = re.match(r'(inner|outer) loop', line)
    if m:
        vertices = []
        loop = {'type': m.group(1), 'vertices' : vertices}
        facet['loops'].append(loop)


    m = re.match(r'vertex (.*)', line)
    if m:
        loop['vertices'].append(m.group(1))


import pprint
pprint.pprint(stl)



Ca prend 3 fois moins de ligne en Perl mais ça oblige a faire des
choses peu élégantes avec les références (et donc une purée de @$..->{}
& co). Mais je me suis forcé à le faire en Python, force est de
constater que c'est limpide du coup.