Modello di visitatore. Operando sui nodi di un albero

4

Sto lavorando con elementi simili a jQuery da cheerio libreria per manipolare le immagini SVG.

Questi oggetti rappresentano nodi XML e hanno una struttura gerarchica interna.

Sto scrivendo una funzione (in JavaScript ovviamente) che visita ogni nodo figlio e, se si tratta di una forma base (ellisse, cerchio, rettangolo ...), calcola un insieme di punti per la forma e invoca un utente funzione fornita con il set di punti e le informazioni sugli elementi.

Lungo la strada, la funzione tiene traccia di tutte le operazioni di trasformazione che sono state specificate fino a quel nodo, in modo che quando genera il punto impostato per una forma, applicherà la scala accumulata, ruoterà, tradurrà le operazioni ecc per quel nodo .

La funzione fornita dall'utente farà cose come generare oggetti poligonali o calcolare caselle di delimitazione.

Esiste uno schema di progettazione standard per questo tipo di funzione? Sembra vagamente come un pattern Visitor, ma in quel caso i nodi avrebbero un'interfaccia Visitor e invocheranno un'operazione da soli. Non voglio modificare gli oggetti cheerio . Inoltre, i nodi non sanno dove si trovano nell'albero e non possono fornire il loro contesto di trasformazione.

Questa non è una routine difficile da scrivere, ma sono interessato a sapere se c'è qualche teoria formale che sia rilevante?

    
posta AdamW 14.03.2017 - 19:02
fonte

1 risposta

1

Per completezza, ho pensato di pubblicare ciò che effettivamente mi è venuto in mente:

//Traverses the SVG tree and invokes userFnc when ever it encounters    
//a Basic Shape node    
function shapesTraverser( jQsvgs, userFnc, transformers = Transformer() ){

        jQsvgs.each( function(){
            let jQ = $( this );

            //parse the SVG 'transform' attribute and append it to
            //the sequence of tranformation operations
            transformers = transformers.cat( jQ.transform() );

            if(isShapeElement( jQ ) ){
                stop = userFnc( jQ, transformers );
            }
            else{//recursive call
                shapes.shapesTraverser( jQ.children(), userFnc, transformers )
            }

        } );
    }

//Rides on the shapeTraverser.  For each Basic Shape, it calculates
//a set of points, applies the transformation ops, and passes the
//result to userFnc
function pointsTraverser( jQsvgs, userFnc ){

        let shapesFunc = function( jQ, transformers ){

            let points = toPoints( jQ );
            points = transformers( ...points );

            userFnc( jQ, points );

        }

        this.shapesTraverser( jQsvgs, shapesFunc )

    }

// Uses pointsTraverser to calculate a bounding box for the whole
// SVG object
function boundingBox( jQsvgs ){
        let box = new BoundingBox();

        function pointsFunc( jQ, points ){
            box.merge( points );
        }

        this.pointsTraverser( jQsvgs, pointsFunc );

        return box;
    }
    
risposta data 15.03.2017 - 19:44
fonte

Leggi altre domande sui tag