Class and Methods.R e Class and Methods extension.R contengono le definizioni delle classi e dei metodi presentati in seguito.
Shapes_list.R contiene le forme sviluppate di default.
Rules_27102022.R contiene le regole per la creazone delle matrici.
La classe field
contiene le informazioni neccessarie per plottare il contenuto di una cella della matrice.
field <- list(
shape = NULL,
size.x = list(),
size.y = list(),
rotation = list(),
pos.x = list(),
pos.y = list(),
lty =list(),
lwd = list(),
num = list(),
nv = list(),
shade =list(),
visible = NULL,
tag = list()
)
shape
è un vettore contente stringhe di caratteri, ogni elemento della stringa indica la forma che si vuole sviluppare, per esempio c('circle','square')
size.x
e size.y
un vettore o un scalare che danno informazione per il semi-asse maggiore e minore del elisse entro il quale è inscritto il poligono (corrispondono a radius.x
e radius.y
del pacchetto DescTools
)
library(DescTools)
Canvas(c(-5,5),c(-5,5)) # non è necessario il secondo c(-5,5) basta Canvas(c(-5,5))
DrawRegPolygon(x = 0, y = 0, radius.x=9,radius.y = 5, nv = 100)
DrawRegPolygon(x = 0, y = 0, radius.x=9,radius.y = 5, nv = 3)
rotation
angolo di rotazione in radianti (corrisponde a rot
del pacchetto DescTools
)
x
e y
un vettore delle coordinate xy del centro del polygono (corrispondono a x
e y
del pacchetto DescTools
)
lty
e lwd
rispettivamente il tipo di linea per il perimetro e lo spessore della stessa.
Le figure di default hanno lty=1
e lwd=2
(corrispondono a lty
e lwd
del pacchetto DescTools
)
num
il numero di volte che un oggetto è ripetuto sulla cella (più un desiderata che altro al momento)
nv
il numero di vertici del poligono (per cerchi/elipsi nv = 100
)
shade
è il riempimento monocromatico di una forma
visible
un vettore binario che contiene un 1 se la forma nella posizione relativa deve venire disegnata, uno 0 se non deve venire disegnata.
Per esempio list(shapes=c('circle','square'), visible = c(0,1))
plottera solo il quadrato e non il cerchio.
La classe Raven_matrix
contiene tutte le informazioni neccessarie per classificare la creazione della matrice.
Raven<-list(
Sq1 = list(),
Sq2 = list(),
Sq3 = list(),
Sq4 = list(),
Sq5 = list(),
Sq6 = list(),
Sq7 = list(),
Sq8 = list(),
Sq9 = list(),
hrule = list(),
vrule = list()
)
I campi da Sq1
a Sq9
corrispondono alle celle della matrice.
## [,1] [,2] [,3]
## [1,] "Sq1" "Sq2" "Sq3"
## [2,] "Sq4" "Sq5" "Sq6"
## [3,] "Sq7" "Sq8" "Sq9"
Ogni cella della matrice andrà a contenere un oggetto di classe field
contenente tutte le possibili forme al suo interno.
I campi hrule
e vrule
sono due vettori contententi le regole.
hrule
contiene le regole che verranno applicate secondo la logica orizzontale. L’ordine delle regole nel vettore corrisponde al ordine di applicazione.vrule
contiene le regole che verranno applicate secondo la logica verticale. L’ordine delle regole nel vettore corrisponde al ordine di applicazione.Logiche più complesse vengono ottenute tramite composizioni di orizzontale e verticale.
La funzione cof
concatena diversi campi esattamente secondo la stessa logica di c()
source("Class and Methods.R")
cof(square(),circle(),pentagon())
## $shape
## [1] "square" "circle" "pentagon"
##
## $size.x
## $size.x[[1]]
## [1] 15
##
## $size.x[[2]]
## [1] 10
##
## $size.x[[3]]
## [1] 15
##
##
## $size.y
## $size.y[[1]]
## [1] 15
##
## $size.y[[2]]
## [1] 10
##
## $size.y[[3]]
## [1] 15
##
##
## $theta.1
## $theta.1[[1]]
## [1] 0
##
## $theta.1[[2]]
## [1] 0
##
## $theta.1[[3]]
## [1] 0
##
##
## $theta.2
## $theta.2[[1]]
## [1] 0
##
## $theta.2[[2]]
## [1] 0
##
## $theta.2[[3]]
## [1] 0
##
##
## $rotation
## $rotation[[1]]
## [1] 0.7853982
##
## $rotation[[2]]
## [1] 0
##
## $rotation[[3]]
## [1] 1.570796
##
##
## $pos.x
## $pos.x[[1]]
## [1] 0
##
## $pos.x[[2]]
## [1] 0
##
## $pos.x[[3]]
## [1] 0
##
##
## $pos.y
## $pos.y[[1]]
## [1] 0
##
## $pos.y[[2]]
## [1] 0
##
## $pos.y[[3]]
## [1] 0
##
##
## $lty
## $lty[[1]]
## [1] 1
##
## $lty[[2]]
## [1] 1
##
## $lty[[3]]
## [1] 1
##
##
## $lwd
## $lwd[[1]]
## [1] 3
##
## $lwd[[2]]
## [1] 2
##
## $lwd[[3]]
## [1] 3
##
##
## $num
## $num[[1]]
## [1] 1
##
## $num[[2]]
## [1] 1
##
## $num[[3]]
## [1] 1
##
##
## $nv
## $nv[[1]]
## [1] 4
##
## $nv[[2]]
## [1] 100
##
## $nv[[3]]
## [1] 5
##
##
## $shade
## $shade[[1]]
## [1] NA
##
## $shade[[2]]
## [1] NA
##
## $shade[[3]]
## [1] NA
##
##
## $visible
## [1] 1 1 1
##
## $tag
## $tag[[1]]
## [1] "simple" "small"
##
## $tag[[2]]
## [1] "simple" "small"
##
## $tag[[3]]
## [1] "simple" "small"
##
##
## attr(,"class")
## [1] "field"
La funzione Raven
crea una matrice di Raven in cui tutte le celle della matrice vengono inizializzate identiche alla cella Sq1
, e vengono inizializzate le regole.
St1
classe field che contiene i campi di partenza per tutte le cellehrule
vettore delle regole applicabili con logica orizzontalevrule
vettore delle regole applicabili con logica verticaleM<-Raven(st1=square(),hrule=c("size"),vrule=c("identity"))
draw(M)
Nella matrice M
le regole non sono ancora state applicate, infatti nel plot d’esempio i quadrati hanno tutti le stesse dimensioni.
L’estensione del metodo apply
applica le regole presenti nella matrice a tutte le celle.
Al momento applica le regole prima in riga e poi in colonna.
M<-apply(M)
draw(M)
Il metodo rotazione cambia il valore field$rotation
di rotazioni fisse con un angolo di \(\frac{\pi}{4}\)
obj
il contenuto di una cella della matricen
rappresenta l’ennesimo elemento a cui viene applicata la regola. Per esempio se la regola viene applicata orizzontalmente n =1
per Sq1
,Sq4
e Sq7
, n =2
per Sq2
,Sq5
e Sq8
e per finire n =3
per Sq3
,Sq6
e Sq9
.rotation.field<-function(obj,n,...) {
obj$rotation[[1]]<-obj$rotation[[1]]+(n-1)*pi/4
return(obj)
}
La rotazione può essere applicata con le regole orizzontali, verticali e diagonalmente da basso a sinistra a alto-destra (TL-LR) applicando prima in orizzontale poi verticale.
#Horizontal
M<-apply(Raven(st1=pentagon(),hrule=c("rotation"),vrule=c("identity")))
draw(M)
#Vertical
M<-apply(Raven(st1=pentagon(),hrule=c("identity"),vrule=c("rotation")))
draw(M)
# Top Left Low Right
M<-apply(Raven(st1=pentagon(),hrule=c("rotation"),vrule=c("rotation")))
draw(M)
Il metodo di cambio di dimensioni, riduce i valori di field$size.x
e field$size.y
di un valore costante pari a numero di riga (o colonna) della matrice per \(k=.9\).
Se per esempio la regola è applicata orizzontalmente, gli elementi nelle celle Sq1,Sq4,sq7
della prima colonna hanno dimensioni \((\frac{x}{k},\frac{y}{k})\), gli elementi nelle celle Sq2,Sq5,sq8
hanno dimensioni \((\frac{x}{2k},\frac{y}{2k})\) e quelli nella terza colonna \((\frac{x}{3k},\frac{y}{3k})\).
size.field<-function(obj,n,...) {
obj$size.x[[1]]<-obj$size.x[[1]]/(n*.9)
obj$size.y[[1]]<-obj$size.y[[1]]/(n*.9)
return(obj)
}
La cambio di dimensione può essere applicata con le regole orizzontali, verticali e diagonalmente da basso a sinistra a alto-destra (TL-LR) applicando prima in orizzontale poi verticale.
#Horizontal
M<-apply(Raven(st1=circle(),hrule=c("size"),vrule=c("identity")))
draw(M)
#Vertical
M<-apply(Raven(st1=circle(),hrule=c("identity"),vrule=c("size")))
draw(M)
# Top Left Low Right
M<-apply(Raven(st1=circle(),hrule=c("size"),vrule=c("size")))
draw(M)
Il metodo di cambio di forma manipola il campo field$visible
in modo di alternare tre diverse forme.
L’ordine di applicazione va dalla terza alla prima forma.
Per ogni cella individua quali forme sono visibili - Se più di una forma è visibile le rende tutte invisibili e seleziona solo quella in posizione \(n\).
Dove \(n\) è l’indice di riga (o di colonna) - Se una sola forma è visibile la regola la mette invisibile e seleziona quella a distante \(n\) nel vettore index
diff_shapes.field<-function(obj,n,...) {
if(length(obj$visible)!=3)
{
stop("You must have at least three forms to change shapes!")
}
#index<-c(3:1,3:1,3:1) TL-LR
index<-c(1:3,1:3,1:3) #TR-LL
pos<-which(obj$visible==1)
if(length(pos)>1){
obj$visible[pos]<-0
obj$visible[index[n]]<-1
}else {
obj$visible[pos]<-0
obj$visible[index[pos+n]]<-1
}
return(obj)
}
Il cambio di forma può essere applicato con le regole orizzontali, verticali e diagonalmente da basso a sinistra a alto-destra (TL-LR) applicando prima in orizzontale poi verticale.
#Horizontal
M<-apply(Raven(st1=cof(circle(),square(),pentagon()),hrule=c("diff_shapes"),vrule=c("identity")))
draw(M)
#Vertical
M<-apply(Raven(st1=cof(circle(),square(),pentagon()),hrule=c("identity"),vrule=c("diff_shapes")))
draw(M)
# Top Left Low Right
M<-apply(Raven(st1=cof(circle(),square(),pentagon()),hrule=c("diff_shapes"),vrule=c("diff_shapes")))
draw(M)
La regola per il cambiamento del contorno può cambiare sia lo spessore che il tipo di contorno utilizzando i parametri standard di R lwd
e lty
.
Tre diversi spessori vengono utilizzati dipendenti dal indice di riga (o di colonna) \(n\).
Le forme di default hanno come spessore di partenza \(2\).
Il tipo di contorno cambia allo stesso modo in funzione del indice di riga (o di colonna) \(n\).
margin.field<-function(obj,n,rules,...){
index<-c(3:1,3:1,3:1)
if(grepl("lwd",rules)){
obj$lwd[[1]]<- index[obj$lwd[[1]]+n]+1
}else if(grepl("lty",rules)){
obj$lty[[1]]<-index[obj$lty[[1]]+n]
}
return(obj)
}
#Horizontal
M<-apply(Raven(st1=pentagon(),hrule=c("lwd"),vrule=c("identity")))
draw(M)
#Vertical
M<-apply(Raven(st1=pentagon(),hrule=c("identity"),vrule=c("lwd")))
draw(M)
# Top Left Low Right
M<-apply(Raven(st1=pentagon(),hrule=c("lwd"),vrule=c("lwd")))
draw(M)
#Horizontal
M<-apply(Raven(st1=pentagon(),hrule=c("lty"),vrule=c("identity")))
draw(M)
#Vertical
M<-apply(Raven(st1=pentagon(),hrule=c("identity"),vrule=c("lty")))
draw(M)
# Top Left Low Right
M<-apply(Raven(st1=pentagon(),hrule=c("lty"),vrule=c("lty")))
draw(M)
Il riempimento monocromatico viene applicato campo per campo.
La regola per il rimepimento monocromatico cambia il campo field$shade
tra i valori white
, black
e grey
.
I tre diversi riempimenti vengono assegnati tramite l’indice di riga (o di colonna) \(n\).
Il solo perimentro si ottiene con field$shade="none"
fill.field<-function(obj,n,...){
index <- rep(c("white","grey","black"),3)
pos <- index==obj$shade[[1]]
if(is.na(sum(pos)))
{
obj$shade[[1]]<-index[n]
}else{
pos <- which(pos)
obj$shade[[1]]<-index[pos+n]
}
return(obj)
}
#Horizontal
M<-apply(Raven(st1=pentagon(),hrule=c("fill"),vrule=c("identity")))
draw(M)
#Vertical
M<-apply(Raven(st1=pentagon(),hrule=c("identity"),vrule=c("fill")))
draw(M)
# Top Left Low Right
M<-apply(Raven(st1=pentagon(),hrule=c("fill"),vrule=c("fill")))
draw(M)
Le regole logiche vengono applicate per riga e per colonna con 3 o più forme. Presento gli elementi basi per applicare la logica in termini insiemistici.
logic.field<-function(obj,n,rule,seed,...) {
if(length(obj$shape)<3)
{
stop("You must have three forms to apply a logical AND !")
}
##gestione di più immagini
domain<-1:length(obj$shape)
obj$visible[domain]<-1
set.seed(seed)
fixed<-sample(domain,round(length(obj$shape)/5))
domain<-setdiff(domain,fixed)
half<-length(domain)%/%2
index<-list()
index[[1]]<-sample(domain,half)
index[[2]]<-sample(setdiff(domain,index[[1]]),half)
if(rule=="AND"){
index[[3]]<-union(index[[1]],index[[2]])
obj$visible[index[[n]]]<-0
}else if(rule=="OR"){
if(n<3){
obj$visible[index[[n]]]<-0
}
}else if(rule=="XOR"){
index[[3]]<-union(setdiff(domain,union(index[[1]],index[[2]])),fixed)
obj$visible[index[[n]]]<-0
}
return(obj)
}
domain
è l’insieme delle forme \(D\)fixed
è l’intersezione tra la prima e la seconda cella \(C_1 \cap C_2\)index[[1]]
è l’insieme delle forme nella prima cella meno l’intersezione \(C_1 / \{ C_1 \cap C_2\}\)index[[2]]
è l’insieme delle forme nella seconda cella meno l’intersezione \(C_2 / \{ C_1 \cap C_2\}\)Questi insiemi vengono mantenuti costanti per riga (o per colonna) tramite dei differenti semi.
#Horizontal
M<-apply(Raven(st1=cof(pentagon(),vertical.eight(),horizontal.eight()),hrule=c("AND"),vrule=c("identity")))
draw(M)
#Vertical
M<-apply(Raven(st1=cof(pentagon(),vertical.eight(),horizontal.eight()),vrule=c("AND"),hrule=c("identity")))
draw(M)
#Horizontal
M<-apply(Raven(st1=cof(pentagon(),vertical.eight(),horizontal.eight()),hrule=c("OR"),vrule=c("identity")))
draw(M)
#Vertical
M<-apply(Raven(st1=cof(pentagon(),vertical.eight(),horizontal.eight()),vrule=c("OR"),hrule=c("identity")))
draw(M)
#Horizontal
M<-apply(Raven(st1=cof(pentagon(),vertical.eight(),horizontal.eight()),hrule=c("XOR"),vrule=c("identity")))
draw(M)
#Vertical
M<-apply(Raven(st1=cof(pentagon(),vertical.eight(),horizontal.eight()),vrule=c("XOR"),hrule=c("identity")))
draw(M)