Protocols de Python

El mode Protocols de python ofereix estilitzacions de línia plenament programables. En aquest mode de control, totes les operacions d’estilització s’escriuen com a protocols de Python anomenats mòduls d’estil en la terminologia de Freestyle. La ingressió a un mòdul d’estil és un mapa de visionat (és a dir, un conjunt d’arestes destacades que s’han detectat) i l’egressió és un conjunt de traços estilitzats.

Un mòdul d’estil es compon d’invocacions successives de cinc operadors bàsics: selecció, encadenament, divisió, ordenació i creació de traços. L’operador de selecció identifica un subconjunt d’arestes destacades d’ingressió que es basen en una o més condicions de selecció definides per la usuària (predicats). Les arestes seleccionades es processen amb els operadors d’encadenament, divisió i ordenació per a confegir cadenes d’arestes destacades. Aquests operadors també estan controlats per predicats i funcions subministrades per la usuària per tal de determinar com transformar les arestes destacades en cadenes. Finalment, l’operador de creació de traços transforma les cadenes en traços estilitzats sobre la base d’una llista d’aspectors de traç que defineix la usuària.

Els mòduls d’estil de Python s’emmagatzemen dins dels documents blend com a blocs de dades de text. Primer cal carregar documents de mòduls d’estil externs a l’Editor de text. Després el menú de selecció dins d’una entrada de l’estiba de mòduls d’estil us permet de seleccionar un mòdul de la llista de mòduls d’estil carregats.

../../_images/render_freestyle_python_scripting-mode.png

Una captura de pantalla d’un mòdul d’estil cartoon.py carregat a l’editor de text (esquerra), així com opcions de Freestyle en el mode de Protocols de python als botons de Capes de visionat (dreta).

Freestyle de Blender ve amb una sèrie de mòduls d’estil de Python que poden servir com a punt de partida perquè us redacteu mòduls d’estils propis. Vegeu també la secció de l’API de Python de Freestyle al manual de referència de l’API de Blender Python per a tots els detalls per confegir mòduls d’estil.

../../_images/render_freestyle_python_scripting-mode-example-1.jpg

Per T.K. utilitzant el mode Protocols de python ( document blend, CC0).

../../_images/render_freestyle_python_scripting-mode-example-2.png

Per T.K. utilitzant el mode Protocols de python ( blend-file, CC0).

Redacció de mòduls d’estil

Un mòdul d’estil és una peça de codi responsable de l’estilització del dibuix lineal Freestyle. La ingressió d’un mòdul d’estil és un conjunt d’arestes destacades que s’anomena mapa de visionat (ViewMap). L’egressió és un joc de línies estilitzades també anomenades traços. Un mòdul d’estil s’estructura com una seqüència d’operacions que permeten de confegir traços des de les arestes d’ingressió dins del mapa de visionat.

Hi ha cinc tipus d’operacions (llistades amb les funcions d’operador corresponents):

  • Selecció Operators.select()

  • Encadenat Operators.chain(), Operators.bidirectional_chain()

  • Divisió Operators.sequential_split(), Operators.recursive_split()

  • Ordenació Operators.sort()

  • Creació de traços Operators.create()

El mapa del visionat d’ingressió està poblat amb un conjunt d’objectes ViewEdge. L’operació de selecció s’utilitza per escollir els ViewEdges que són d’interès per les artistes basant-se en les condicions de selecció definides per la usuària (predicats). Les operacions d’encadenament agafen el subconjunt de ViewEdges i confegeixen Cadenes a base de concatenar ViewEdges segons els predicats i funcions que defineix la usuària. Les cadenes es poden refinar encara més dividint-les en peces més petites (p. ex. en punts on les arestes facin un gir agut) i seleccionant-ne una fracció (p. ex. per mantenir només aquelles que són més llargues que un llindar de longitud). L’operació d’ordenació s’utilitza per organitzar l’ordre d’estibament de les cadenes per dibuixar una línia sobre l’altra. Les cadenes es transformen finalment en traços estilitzats mitjançant l’operació de creació de traç tot aplicant una sèrie de aspectors de traç a cadenes individuals.

ViewEdges, Cadenes i Traços fan referència de forma genèrica a elements unidimensionals (1D). Un element 1D és una polilínia que és una sèrie de línies rectes connectades. Els vèrtexs d’elements 1D s’anomenen en general elements 0D.

Tots els operadors actuen sobre un conjunt d’elements 1D actius. El conjunt actiu inicial és el conjunt de ViewEdges en el mapa de visionat d’ingressió. El conjunt actiu l’actualitzen els operadors.

Selecció

L’operador de selecció passa per tots els elements del conjunt actiu i manté només els que satisfan un determinat predicat. El mètode Operators.select() agafa com a argument un predicat unari que funciona en qualsevol Interface1D que representi un element 1D. Per exemple:

Operators.select(QuantitativeInvisibilityUP1D(0))

Aquesta operació de selecció utilitza el predicat QuantitativeInvisibilityUP1D per a seleccionar només el ViewEdge visible (per ser més precís, aquells la invisibilitat quantitativa dels quals és igual a 0). L’operador de selecció està orientat a aplicar selectivament l’estil a una fracció dels elements 1D actius.

S’observa que QuantitativeInvisibilityUP1D és una classe que implementa el predicat que posa a prova la visibilitat de la línia i que el mètode Operators.select() agafa una instància de la classe del predicat com a argument. La prova del predicat per a un determinat element 1D es realitza invocant la instància del predicat, és a dir, invocant el mètode __call__ de la classe de predicat. En altres paraules, el mètode Operators.select() agafa com a argument un functor que al seu torn agafa un objecte Interface0D com a argument. L’API Freestyle de python empra els functors àmpliament per implementar predicats així com funcions.

Encadenament

Els operadors d’encadenament actuen sobre el conjunt d’objectes ViewEdge actius i determinen la topologia dels futurs traços. La idea és implementar un iterador per travessar la gràfica del ViewMap tot seguint els ViewEdges. L’iterador defineix una regla d’encadenament que determina el ViewEdge següent a seguir des d’un vèrtex donat (vegeu ViewEdgeIterator). Hi ha a disposició diversos iteradors d’aquesta mena com a part de l’API de Freestyle de Python (vegeu ChainPredicateIterator i ChainSilhouetteIterator). Es poden definir iterators personalitzats per la via d’heretar la classe ViewEdgeIterator. L’operador d’encadenament també pren com a argument un UnaryPredicate que opera en la Interface1D com a criteri d’aturada. L’encadenament s’atura quan, durant la marxa que segueix la gràfica, l’iterador ha arribat a un ViewEdge que satisfà aquest predicat.

La cadena pot ser Operators.chain() unidireccional o Operators.bidirectional_chain() bidireccional. En aquest últim cas, l’encadenat es propagarà en les dues direccions des de l’aresta inicial.

El que segueix és un exemple de codi d’encadenat bidireccional:

Operators.bidirectional_chain(
        ChainSilhouetteIterator(),
        NotUP1D(QuantitativeInvisibilityUP1D(0)),
        )

L’operador d’encadenat utilitza el ChainSilhouetteIterator com a regla d’encadenament i deixa d’encadenar tan aviat com l’iterador ha arribat a un ViewEdge invisible.

Els operadors d’encadenat processen el conjunt d’objectes ViewEdge actius per ordre. Els ViewEdges actius es poden ordenar prèviament utilitzant el mètode Operators.sort() (vegeu més avall). Comença una cadena amb el primer ViewEdge del conjunt actiu. Tots els ViewEdges que ja han estat implicats en el procés d’encadenat estan marcats (en el cas de l’exemple de dalt, la llegenda de temps de cada ViewEdge es modifica per defecte), per tal de no processar el mateix ViewEdge dos cops. Una vegada l’encadenat arriba a un ViewEdge que satisfà el predicat d’aturada, es posa fi a la cadena. A continuació, s’inicia una nova cadena des del primer ViewEdge sense marcar al conjunt actiu. Aquesta operació es repeteix fins que s’ha processat l’últim ViewEdge no marcat del conjunt actiu. Al final de l’operació d’encadenat, el conjunt actiu queda definit per les Cadenes que s’acaben de confegir.

Divisió

L’operació de divisió s’utilitza per refinar la topologia de cada Cadena. La divisió es realitza de forma o bé seqüencial o bé recursiva. La divisió seqüencial Operators.sequentialSplit(), en la seva forma bàsica, analitza la Cadena a una resolució arbitrària donada i avalua un predicat unari (treballant sobre elements 0D) en cada punt del llarg de la Cadena. Cada vegada que es compleix el predicat, la cadena es divideix en dues cadenes. Al final de l’operació de divisió seqüencial, el conjunt actiu de cadenes queda definit per les noves cadenes.

Operators.sequentialSplit(TrueUP0D(), 2)

En aquest exemple, la cadena es divideix cada 2 unitats. Una versió més elaborada utilitza dos predicats en lloc d’un: un per determinar el punt d’inici de la nova cadena i l’altre per determinar el seu punt final. Aquesta segona versió pot donar com a resultat un conjunt de Cadenes disjuntades o que se superposen si els dos predicats són diferents (vegeu Operators.sequentialSplit() per més detalls).

La divisió recursiva Operators.recursiveSplit() avalua una funció sobre els elements 0D al llarg de la Cadena a una resolució donada i troba el punt que dona el valor màxim de la funció. La Cadena aleshores es divideix en dos en aquest punt. Aquest procés es repeteix recursivament en cadascuna de les dues noves Cadenes fins que la Cadena d’ingressió satisfà una condició d’aturada especificada per la usuària.

func = Curvature2DAngleF0D()
Operators.recursive_split(func, NotUP1D(HigherLengthUP1D(5)), 5)

En l’exemple del codi anterior, les Cadenes es divideixen recursivament en punts de la curvatura 2D més alta. La curvatura s’avalua en punts al llarg de la Cadena a una resolució de 5 unitats. Les Cadenes de menys de 5 unitats ja no es dividiran.

Ordenació:

L’operador d’ordenació Operators.sort() organitza l’ordre d’estibament dels elements 1D actius. Pren com a argument un predicat binari utilitzat com a operador «més petit que» per ordenar dos elements 1D.

Operators.sort(Length2DBP1D())

En aquest exemple de codi, l’ordenació utilitza el predicat binari Length2DBP1D per a ordenar els objectes Interface1D en l’ordre ascendent en termes de longitud 2D.

L’ordenació és particularment útil quan es combina amb la densitat causal. Encara més, la densitat causal avalua la densitat de la imatge resultant a mesura que es modifica. Si volem utilitzar aquesta eina per a decidir d’eliminar els traços sempre que la densitat local sigui massa alta, és important controlar l’ordre en què es dibuixen els traços. En aquest cas, utilitzaríem l’operador d’ordenació per a assegurar que primer es dibuixen les línies més «importants».

Creació de traços

Finalment, l’operador de creació de traços Operators.create() agafa el conjunt actiu de Cadenes com a traços d’ingressió i construcció. L’operador agafa dos arguments. El primer és un predicat unari que funciona sobre Interface1D i que està dissenyat per fer una última selecció sobre el conjunt de Cadenes. Una Cadena que no satisfaci la condició no esdevindrà un Traç. La segona ingressió és una llista d’aspectors que seran responsables de l’aspecció de cada traç confegit.

shaders_list = [
    SamplingShader(5.0),
    ConstantThicknessShader(2),
    ConstantColorShader(0.2,0.2,0.2,1),
    ]
Operators.create(DensityUP1D(8,0.1, IntegrationType.MEAN), shaders_list)

En aquest exemple, el predicat DensityUP1D s’utilitza per suprimir totes les Cadenes la densitat mitjana de les quals és superior a 0,1. Cada cadena es transforma en un traç després de remostrejar-la per tenir un punt cada 5 unitats i assignant-li un gruix constant de 2 unitats i un color constant gris fosc.

Control d’usuària sobre la definició de la via de producció

El redactat de mòduls d’estil ofereix diferents tipus de control per a la usuària, tot i que els mòduls d’estil individuals tenen una via de producció d’estructura fixa. Un és la seqüenciació de diferents estructures de control de les vies de producció i l’altre és a través de la definició d’objectes functors que es passen com a argument per la via de producció.

Es poden definir diferents estructures de control de via de producció tot seqüenciant les operacions de selecció, encadenat, divisió i ordenació. La creació dels traços és sempre l’última operació que conclou un mòdul d’estil.

Els predicats, funcions, iteradors d’encadenats i els aspectors de traç es poden definir heretant classes base i sobreseient els mètodes apropiats. Vegeu les entrades manuals de referència de les següents classes base per més informació sobre els constructes protocolitzables que pot redactar la usuària.

Vegeu també

Els predictors, funcions, iteradors d’encadenaments i els aspectors de traç es poden definir heretant les classes base i sobreseient els mètodes apropiats. Vegeu Freestyle python module per a tenir més informació sobre els constructes que una usuària pot redactar.