NSAffineTransform — cos'è, tipi di trasformazioni e come applicarle

Autore: IT Sectr Pubblicato: 2026-07-22 Tempo di lettura: 9 min

NSAffineTransform è una classe di AppKit (macOS) che rappresenta una trasformazione affine nella grafica bidimensionale. Incapsula una matrice 3×3 che descrive una combinazione di traslazione, scala, rotazione e taglio delle coordinate. Secondo la Documentazione Apple (2026), NSAffineTransform è ampiamente utilizzato in Core Graphics per trasformare percorsi, punti e contesti grafici su macOS.

Punti Chiave

  • NSAffineTransform è una classe AppKit per trasformazioni affini su macOS con una matrice 3×3
  • Trasformazione affine preserva il parallelismo delle linee ma può modificare distanze e angoli
  • Operazioni di base: translate (traslazione), scale (scala), rotate (rotazione), shear (taglio)
  • Le trasformazioni si combinano tramite moltiplicazione di matrici — l'ordine delle operazioni influenza il risultato
  • NSAffineTransform si applica a punti, dimensioni, percorsi e al contesto Core Graphics

Cos'è NSAffineTransform?

NSAffineTransform è una classe del framework AppKit, disponibile solo su macOS. Rappresenta una trasformazione affine nello spazio bidimensionale attraverso una matrice 3×3. A differenza di CGAffineTransform di Core Graphics (disponibile su iOS), NSAffineTransform è un wrapper orientato agli oggetti attorno alla struttura CGAffineTransform, aggiungendo metodi convenienti per lavorare con NSBezierPath, NSPoint e NSSize.

Una trasformazione affine è una trasformazione del piano che preserva la relazione “il punto giace su una linea” e il parallelismo delle linee. In altre parole, dopo una trasformazione affine, le linee parallele rimangono parallele e le linee rette rimangono rette. Tuttavia, distanze, angoli e aree possono cambiare: scala, rotazione e taglio sono casi speciali di trasformazioni affini.

Su iOS, l'equivalente di NSAffineTransform è la struttura CGAffineTransform di Core Graphics. Entrambe le API si basano sullo stesso modello matematico — una matrice di trasformazione affine 3×3 in cui l'ultima riga è sempre [0, 0, 1]. La differenza è che NSAffineTransform è una classe (con retain/release in Objective-C), mentre CGAffineTransform è una struttura (tipo valore) in Swift e C.

Tipi di trasformazioni affini

NSAffineTransform supporta quattro tipi fondamentali di trasformazioni: translate (traslazione), scale (scala), rotate (rotazione) e shear (taglio). Ogni tipo è rappresentato da un metodo separato e può essere applicato a un oggetto di trasformazione esistente o utilizzato per crearne uno nuovo.

OperazioneMetodo NSAffineTransformParametriEffetto visivo
TranslatetranslateXBy:yBy:deltaX, deltaYSposta l'oggetto lungo gli assi X e Y
ScalescaleBy: / scaleXBy:yBy:factor / scaleX, scaleYIngrandisce o riduce le dimensioni
RotaterotateByDegrees: / rotateByRadians:angolo in gradi o radiantiRuota attorno all'origine
ShearTramite setTransformStructcomponenti m12, m21 della matriceInclina l'oggetto lungo un asse

Translate — Traslazione

Translate aggiunge un offset alle coordinate di tutti i punti di un oggetto. I parametri deltaX e deltaY impostano rispettivamente la quantità di spostamento orizzontale e verticale. Un valore positivo di deltaX sposta a destra, deltaY verso l'alto. Translate non modifica la forma o le dimensioni dell'oggetto — solo la sua posizione.

Scale — Scala

Scale moltiplica le coordinate dei punti per un dato fattore. Con la scala uniforme (un singolo parametro), l'oggetto si ingrandisce o si riduce proporzionalmente. Con la scala non uniforme, la forma viene distorta. Un fattore di 1,0 lascia le dimensioni invariate, maggiore di 1,0 ingrandisce, da 0,0 a 1,0 riduce. I valori negativi creano un riflesso speculare.

Rotate — Rotazione

Rotate ruota l'oggetto attorno all'origine di un dato angolo. Un angolo di rotazione positivo corrisponde a una rotazione antioraria. rotateByDegrees accetta gradi (0–360), rotateByRadians accetta radianti (0–2π). La rotazione viene sempre eseguita rispetto al punto (0, 0), quindi per ruotare attorno a un punto arbitrario, è necessario combinare rotate con translate.

Rappresentazione matriciale 3×3

La trasformazione affine in NSAffineTransform è rappresentata da una matrice 3×3 in cui l'ultima riga è sempre [0, 0, 1]. Questa è la rappresentazione matematica standard che consente di rappresentare una combinazione di trasformazioni come prodotto di matrici. La struttura della matrice è definita tramite NSAffineTransformStruct, che contiene sei componenti significativi: m11, m12, m21, m22, tX, tY.

I componenti m11, m12, m21, m22 sono responsabili di scala, rotazione e taglio. I componenti tX e tY sono responsabili della traslazione. Nella configurazione standard (matrice identità), m11 = 1, m22 = 1 e gli altri sono 0. Per ottenere i valori correnti della matrice, si usa transformStruct — la proprietà di NSAffineTransform che restituisce una struttura NSAffineTransformStruct.

La moltiplicazione di matrici è un'operazione non commutativa. Ciò significa che l'ordine di applicazione delle trasformazioni è importante: translate + rotate dà un risultato diverso da rotate + translate. Durante la combinazione, NSAffineTransform moltiplica la nuova matrice a sinistra per la matrice corrente: newMatrix = operation × currentMatrix. Pertanto, l'ultima trasformazione aggiunta viene applicata per prima.

Composizione di trasformazioni

NSAffineTransform consente di combinare più trasformazioni in un singolo oggetto. Ogni chiamata a translateXBy:yBy:, scaleBy: o rotateByDegrees: modifica la matrice interna — moltiplica la matrice corrente per la matrice della trasformazione corrispondente. Ciò consente di creare una trasformazione complessa da una sequenza di operazioni semplici.

Per invertire una trasformazione combinata, si usa il metodo invert. L'inversa crea una nuova trasformazione affine che annulla quella originale: se si applica la trasformazione originale a un punto e poi l'inversa, il punto torna alla sua posizione originale. L'inversione è utile per annullare una trasformazione del contesto prima di disegnare elementi UI che non devono essere trasformati.

Per verificare se una trasformazione è identità (non modifica le coordinate), si usa la proprietà isIdentity. La trasformazione identità è una matrice unitaria — moltiplicare per essa lascia invariate le coordinate del punto. Un nuovo oggetto NSAffineTransform viene creato come trasformazione identità. Questa proprietà è utile per l'ottimizzazione: se la trasformazione è identità, la sua applicazione può essere saltata.

Applicazione a oggetti e contesto

NSAffineTransform può essere applicato a quattro tipi di oggetti: NSPoint, NSSize, NSBezierPath e il contesto grafico NSGraphicsContext. Per ogni destinazione esiste un metodo separato: transformPoint:, transformSize:, transformBezierPath: e set.

Trasformazione di punti e dimensioni

Il metodo transformPoint: moltiplica la matrice di trasformazione per il vettore di coordinate del punto (x, y, 1), restituendo la nuova posizione del punto. transformSize: funziona in modo simile ma non tiene conto dei componenti tX e tY — la traslazione non viene applicata, solo scala, rotazione e taglio. Ciò è utile per trasformare vettori e dimensioni che non devono essere spostati.

Trasformazione di percorsi NSBezierPath

Il metodo transformBezierPath: crea un nuovo oggetto NSBezierPath, ogni punto del quale viene trasformato secondo la matrice NSAffineTransform. Il percorso originale non viene modificato — viene creata una copia con coordinate trasformate. Questa è un'operazione costosa per percorsi complessi con un gran numero di nodi.

Applicazione al contesto grafico

Il metodo set applica la trasformazione al contesto grafico corrente (NSGraphicsContext), modificando la sua CTM (Current Transformation Matrix). Dopo aver chiamato set, tutto il disegno successivo in questo contesto verrà trasformato. Per trasformazioni temporanee, usa saveGraphicsState / restoreGraphicsState prima e dopo set.

Esempi di codice Swift

Vediamo esempi pratici di utilizzo di NSAffineTransform in un'applicazione macOS per trasformare oggetti grafici.

Creazione e composizione di trasformazioni

Questo esempio crea un NSAffineTransform che combina traslazione, rotazione e scala. Prima, l'oggetto viene spostato di (100, 50), poi ruotato di 45 gradi e infine scalato di 1,5 volte. L'ordine è importante: ruotare dopo aver traslato ruota rispetto alla nuova origine.

swift
import AppKit

let transform = NSAffineTransform()
transform.translateXBy(100, yBy: 50)
transform.rotateByDegrees(45)
transform.scaleBy(1.5)

// Applicazione al punto
let point = NSPoint(x: 10, y: 20)
let transformedPoint = transform.transform(point)

// Applicazione alla dimensione
let size = NSSize(width: 100, height: 50)
let transformedSize = transform.transform(size)

Trasformazione del contesto per il disegno

Questo esempio dimostra l'applicazione di NSAffineTransform a un contesto grafico tramite set e concat. Dopo aver applicato la trasformazione, tutto il disegno successivo viene eseguito nel sistema di coordinate trasformato. Salvare lo stato grafico tramite saveGraphicsState consente di tornare alla matrice originale.

swift
func drawWithTransform(in rect: NSRect) {
    guard let ctx = NSGraphicsContext.current
    else { return }

    ctx.saveGraphicsState()

    let xfm = NSAffineTransform()
    xfm.translateXBy(rect.midX, yBy: rect.midY)
    xfm.rotateByDegrees(30)
    xfm.scaleBy(0.8)
    xfm.concat()

    // Disegno nel sistema di coordinate trasformato
    let path = NSBezierPath(roundedRect: NSRect(
        x: -50, y: -50,
        width: 100, height: 100
    ), xRadius: 10, yRadius: 10)
    NSColor.blue.setFill()
    path.fill()

    ctx.restoreGraphicsState()
}

Trasformazione di un NSBezierPath

Questo esempio dimostra la creazione di una copia di un NSBezierPath con coordinate trasformate. Il percorso originale rimane invariato e la copia trasformata può essere disegnata separatamente — questo è utile per creare elementi ripetuti in posizioni diverse.

swift
func createTransformedTriangle() -> NSBezierPath {
    let triangle = NSBezierPath()
    triangle.move(to: NSPoint(x: 0, y: 0))
    triangle.line(to: NSPoint(x: 100, y: 0))
    triangle.line(to: NSPoint(x: 50, y: 100))
    triangle.close()

    let xfm = NSAffineTransform()
    xfm.translateXBy(200, yBy: 100)
    xfm.scaleXBy(1.5, yBy: 1.5)
    xfm.rotateByDegrees(45)

    let transformed = xfm.transform(triangle)
    return transformed
}

Domande frequenti

Qual è la differenza tra NSAffineTransform e CGAffineTransform?

NSAffineTransform è una classe di AppKit (solo macOS), mentre CGAffineTransform è una struttura di Core Graphics (iOS e macOS). NSAffineTransform è un wrapper orientato agli oggetti e fornisce metodi per lavorare con NSBezierPath. CGAffineTransform è una struttura leggera di tipo valore utilizzata con CGPath.

Come ruotare un oggetto attorno al suo centro?

Per ruotare attorno al centro, esegui tre passaggi: 1) traslare al centro dell'oggetto (spostare l'origine al centro), 2) ruotare dell'angolo desiderato, 3) traslare indietro per il vettore centro negativo. La combinazione traslazione—rotazione—traslazione dà una rotazione attorno a un punto arbitrario, anziché attorno all'origine.

Posso usare NSAffineTransform su iOS?

No, NSAffineTransform è disponibile solo su macOS come parte di AppKit. Su iOS viene utilizzata la struttura CGAffineTransform di Core Graphics, che fornisce funzionalità simili: CGAffineTransformMakeTranslation, CGAffineTransformMakeScale, CGAffineTransformMakeRotation e CGAffineTransformConcat.

Come annullare una trasformazione?

Usa il metodo invert, che restituisce la trasformazione inversa. Se moltiplichi la trasformazione originale per l'inversa, ottieni una matrice unitaria (trasformazione identità). Per un'applicazione temporanea, chiama saveGraphicsState prima di set e restoreGraphicsState dopo.

Come creare un riflesso speculare?

Usa scala negativa: transform.scaleXBy(-1, yBy: 1) crea un riflesso orizzontale, mentre scaleXBy(1, yBy: -1) crea un riflesso verticale. Per riflettere rispetto a un asse arbitrario, combina translate (spostamento sull'asse), scale con -1 e translate inverso.

Riepilogo

  • NSAffineTransform è una classe AppKit per trasformazioni affini con matrice 3×3 su macOS
  • Quattro tipi base: translate (traslazione), scale (scala), rotate (rotazione) e shear (taglio)
  • La matrice 3×3 contiene sei componenti significativi: m11, m12, m21, m22, tX, tY
  • L'ordine di combinazione delle trasformazioni influenza il risultato — la moltiplicazione di matrici non è commutativa
  • Si applica a NSPoint, NSSize, NSBezierPath e al contesto grafico tramite CTM
  • Inversione tramite il metodo invert annulla qualsiasi trasformazione affine
  • Su iOS, l'equivalente è la struttura CGAffineTransform di Core Graphics

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche