NSAffineTransform — ce este, tipuri de transformări și cum se aplică

Autor: IT Sectr Publicat: 2026-07-22 Timp de citire: 9 min

NSAffineTransform — este o clasă din AppKit (macOS) care reprezintă o transformare afină în grafica bidimensională. Încapsulează o matrice 3×3 care descrie o combinație de translație, scalare, rotire și înclinare a coordonatelor. Conform Apple Documentation (2026), NSAffineTransform este utilizat pe scară largă în Core Graphics pentru transformarea traseelor, punctelor și contextelor grafice pe macOS.

Principalele

  • NSAffineTransform — clasă AppKit pentru transformări afine pe macOS cu matrice 3×3
  • Transformarea afină păstrează paralelismul liniilor, dar poate modifica distanțele și unghiurile
  • Operații principale: translate (translație), scale (scalare), rotate (rotire), shear (înclinare)
  • Transformările se combină prin înmulțirea matricelor — ordinea operațiilor influențează rezultatul
  • NSAffineTransform se aplică punctelor, dimensiunilor, traseelor și contextului grafic Core Graphics

Ce este NSAffineTransform?

NSAffineTransform — este o clasă din framework-ul AppKit, disponibilă doar pe macOS. Reprezintă o transformare afină în spațiul bidimensional printr-o matrice 3×3. Spre deosebire de CGAffineTransform din Core Graphics (care este disponibil pe iOS), NSAffineTransform este un înveliș orientat pe obiecte al structurii CGAffineTransform, adăugând metode convenabile pentru lucrul cu NSBezierPath, NSPoint și NSSize.

Transformarea afină — este o transformare a planului care păstrează relația „punctul se află pe o dreaptă” și paralelismul dreptelor. Cu alte cuvinte, după o transformare afină, liniile paralele rămân paralele, iar dreptele — drepte. Cu toate acestea, distanțele, unghiurile și ariile se pot modifica: scalarea, rotirea și înclinarea sunt cazuri particulare ale transformărilor afine.

Pe iOS, echivalentul NSAffineTransform este structura CGAffineTransform din Core Graphics. Ambele API-uri se bazează pe același model matematic — matricea de transformare afină 3×3, unde ultimul rând este întotdeauna [0, 0, 1]. Diferența constă în faptul că NSAffineTransform este o clasă (cu retain/release în Objective-C), iar CGAffineTransform este o structură (tip de valoare) în Swift și C.

Tipuri de transformări afine

NSAffineTransform suportă patru tipuri de bază de transformări: translate (translație), scale (scalare), rotate (rotire) și shear (înclinare). Fiecare tip este reprezentat printr-o metodă separată și poate fi aplicat atât unui obiect de transformare existent, cât și utilizat pentru a crea unul nou.

OperațieMetoda NSAffineTransformParametriEfect vizual
TranslatetranslateXBy:yBy:deltaX, deltaYDeplasarea obiectului de-a lungul axelor X și Y
ScalescaleBy: / scaleXBy:yBy:factor / scaleX, scaleYMărirea sau micșorarea dimensiunilor
RotaterotateByDegrees: / rotateByRadians:unghi în grade sau radianiRotirea în jurul originii coordonatelor
ShearPrin setTransformStructcomponentele m12, m21 ale matriceiÎnclinarea obiectului de-a lungul axei

Translate — translație

Translate adaugă o deplasare la coordonatele tuturor punctelor obiectului. Parametrii deltaX și deltaY specifică magnitudinea deplasării pe orizontală și respectiv pe verticală. O valoare pozitivă deltaX deplasează la dreapta, deltaY — în sus. Translate nu modifică forma sau dimensiunea obiectului — doar poziția acestuia.

Scale — scalare

Scale multiplică coordonatele punctelor cu un factor dat. La scalarea uniformă (un singur parametru), obiectul se mărește sau se micșorează proporțional. La scalarea neuniformă, forma se denaturează. Factorul 1.0 lasă dimensiunea neschimbată, mai mare de 1.0 — mărește, de la 0.0 la 1.0 — micșorează. Valorile negative creează oglindire.

Rotate — rotire

Rotate rotește obiectul în jurul originii coordonatelor cu un unghi dat. Unghiul de rotație pozitiv corespunde rotației în sens invers acelor de ceas. rotateByDegrees acceptă grade (0–360), rotateByRadians — radiani (0–2π). Rotirea se efectuează întotdeauna față de punctul (0, 0), prin urmare pentru rotirea în jurul unui punct arbitrar, rotate trebuie combinat cu translate.

Reprezentarea matriceală 3×3

Transformarea afină în NSAffineTransform este reprezentată de o matrice 3×3, unde ultimul rând este întotdeauna [0, 0, 1]. Aceasta este o reprezentare matematică standard care permite prezentarea combinației de transformări ca produs de matrice. Structura matricei este definită prin NSAffineTransformStruct, care conține șase componente semnificative: m11, m12, m21, m22, tX, tY.

Componentele m11, m12, m21, m22 sunt responsabile pentru scalare, rotire și înclinare. Componentele tX și tY — pentru translație. În configurația standard (matricea unitate) m11 = 1, m22 = 1, celelalte sunt 0. Pentru obținerea valorilor curente ale matricei se utilizează transformStruct — proprietatea NSAffineTransform care returnează structura NSAffineTransformStruct.

Înmulțirea matricelor este o operație necomutativă. Aceasta înseamnă că ordinea aplicării transformărilor contează: translate + rotate dă un rezultat diferit de rotate + translate. La combinare, NSAffineTransform înmulțește noua matrice la stânga cu matricea curentă: newMatrix = operation × currentMatrix. Prin urmare, ultima transformare adăugată se aplică prima.

Combinarea transformărilor

NSAffineTransform permite combinarea mai multor transformări într-un singur obiect. Fiecare apel translateXBy:yBy:, scaleBy: sau rotateByDegrees: modifică matricea internă — înmulțește matricea curentă cu matricea transformării corespunzătoare. Aceasta permite crearea unei transformări complexe dintr-o secvență de operații simple.

Pentru inversarea transformării combinate se utilizează metoda invert. Inversa creează o nouă transformare afină care anulează transformarea originală: dacă aplicăm unui punct transformarea originală, apoi pe cea inversată, punctul revine la poziția inițială. Inversa este utilă pentru anularea transformării contextului înainte de desenarea elementelor UI care nu trebuie să fie transformate.

Verificarea dacă transformarea este identitate (nu modifică coordonatele) se poate face prin proprietatea isIdentity. Transformarea de identitate este matricea unitate, la înmulțirea cu care coordonatele punctului nu se modifică. Un nou obiect NSAffineTransform este creat ca transformare de identitate. Această proprietate este utilă pentru optimizare: dacă transformarea este de identitate, aplicarea ei poate fi omisă.

Aplicarea la obiecte și context

NSAffineTransform poate fi aplicat la patru tipuri de obiecte: NSPoint, NSSize, NSBezierPath și contextul grafic NSGraphicsContext. Pentru fiecare scop există o metodă separată: transformPoint:, transformSize:, transformBezierPath: și set.

Transformarea punctelor și dimensiunilor

Metoda transformPoint: înmulțește matricea de transformare cu vectorul de coordonate al punctului (x, y, 1), returnând noua poziție a punctului. transformSize: funcționează similar, dar nu ia în considerare componentele tX și tY — translația nu se aplică, doar scalarea, rotirea și înclinarea. Acest lucru este util pentru transformarea vectorilor și dimensiunilor care nu trebuie să fie deplasate.

Transformarea traseelor NSBezierPath

Metoda transformBezierPath: creează un nou obiect NSBezierPath, fiecare punct al căruia este transformat conform matricei NSAffineTransform. Traseul original nu se modifică — se creează o copie cu coordonate transformate. Aceasta este o operație costisitoare pentru trasee complexe cu un număr mare de noduri.

Aplicarea la contextul grafic

Metoda set aplică transformarea la contextul grafic curent (NSGraphicsContext), modificând CTM-ul (Current Transformation Matrix). După apelarea set, toate desenările ulterioare în acest context vor fi transformate. Pentru transformarea temporară, utilizați saveGraphicsState / restoreGraphicsState înainte și după set.

Exemple de cod în Swift

Să examinăm exemple practice de utilizare a NSAffineTransform într-o aplicație macOS pentru transformarea obiectelor grafice.

Crearea și combinarea transformărilor

Exemplul creează un NSAffineTransform care combină translația, rotirea și scalarea. Mai întâi obiectul este deplasat cu (100, 50), apoi rotit cu 45 de grade și, în final, mărit de 1.5 ori. Ordinea contează: rotate după translate produce rotirea față de noua origine a coordonatelor.

swift
import AppKit

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

// Aplicare la punct
let point = NSPoint(x: 10, y: 20)
let transformedPoint = transform.transform(point)

// Aplicare la dimensiune
let size = NSSize(width: 100, height: 50)
let transformedSize = transform.transform(size)

Transformarea contextului pentru desenare

Exemplul arată aplicarea NSAffineTransform la contextul grafic prin set și concat. După aplicarea transformării, toate desenările ulterioare se efectuează în sistemul de coordonate transformat. Salvarea stării grafice prin saveGraphicsState permite revenirea la matricea originală.

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()

    // Desenare în sistemul de coordonate transformat
    let path = NSBezierPath(roundedRect: NSRect(
        x: -50, y: -50,
        width: 100, height: 100
    ), xRadius: 10, yRadius: 10)
    NSColor.blue.setFill()
    path.fill()

    ctx.restoreGraphicsState()
}

Transformarea traseului NSBezierPath

Exemplul demonstrează crearea unei copii a NSBezierPath cu coordonate transformate. Traseul original rămâne neschimbat, iar copia transformată poate fi desenată separat — acest lucru este util pentru crearea elementelor repetitive în diferite poziții.

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
}

Întrebări frecvente

Cu ce diferă NSAffineTransform de CGAffineTransform?

NSAffineTransform — este o clasă din AppKit (doar macOS), iar CGAffineTransform — este o structură din Core Graphics (iOS și macOS). NSAffineTransform este un înveliș orientat pe obiecte și oferă metode pentru lucrul cu NSBezierPath. CGAffineTransform este o structură ușoară de tip valoare utilizată cu CGPath.

Cum rotim un obiect în jurul centrului său?

Pentru rotirea în jurul centrului, executați trei pași: 1) translate la centrul obiectului (deplasarea originii coordonatelor în centru), 2) rotate cu unghiul dorit, 3) translate înapoi cu vectorul negativ al centrului. Combinația translate—rotate—translate oferă rotație în jurul unui punct arbitrar, nu în jurul originii coordonatelor.

Pot folosi NSAffineTransform pe iOS?

Nu, NSAffineTransform este disponibil doar pe macOS în cadrul AppKit. Pe iOS se utilizează structura CGAffineTransform din Core Graphics, care oferă capacități similare: CGAffineTransformMakeTranslation, CGAffineTransformMakeScale, CGAffineTransformMakeRotation și CGAffineTransformConcat.

Cum anulăm o transformare?

Utilizați metoda invert, care returnează transformarea inversă. Dacă înmulțim transformarea originală cu cea inversată, obținem matricea unitate (transformarea de identitate). Pentru aplicarea temporară, apelați saveGraphicsState înainte de set și restoreGraphicsState după.

Cum creăm o oglindire?

Utilizați scara negativă: transform.scaleXBy(-1, yBy: 1) creează oglindirea orizontală, iar scaleXBy(1, yBy: -1) — oglindirea verticală. Pentru oglindirea față de o axă arbitrară, combinați translate (deplasare pe axă), scale cu -1 și translate invers.

Rezumat

  • NSAffineTransform — clasă AppKit pentru transformări afine cu matrice 3×3 pe macOS
  • Patru tipuri de bază: translate (translație), scale (scalare), rotate (rotire) și shear (înclinare)
  • Matricea 3×3 conține șase componente semnificative: m11, m12, m21, m22, tX, tY
  • Ordinea combinării transformărilor influențează rezultatul — înmulțirea matricelor este necomutativă
  • Se aplică la NSPoint, NSSize, NSBezierPath și contextul grafic prin CTM
  • Inversa prin metoda invert anulează efectul oricărei transformări afine
  • Pe iOS, echivalentul este structura CGAffineTransform din Core Graphics

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și