NSAffineTransform — шта је то, врсте трансформација и како примењивати

Аутор: IT Sectr Објављено: 2026-07-22 Време читања: 9 мин

NSAffineTransform — је класа из AppKit-а (macOS) која представља афино преображај у дводимензионалној графици. Она инкапсулира матрицу 3×3 која описује комбинацију помијерања, скалирања, ротације и кошења координата. Према Apple Documentation (2026), NSAffineTransform се широко користи у Core Graphics за трансформацију путања, тачака и графичких контекста на macOS-у.

Главно

  • NSAffineTransform — класа AppKit-а за афине трансформације на macOS-у са матрицом 3×3
  • Афино преображај чува паралелност линија, али може мијењати удаљености и углове
  • Основне операције: translate (помијерање), scale (скалирање), rotate (ротација), shear (кошење)
  • Трансформације се комбинују множењем матрица — редослед операција утиче на резултат
  • NSAffineTransform се примјењује на тачке, величине, путање и графички контекст Core Graphics-а

Шта је NSAffineTransform?

NSAffineTransform — је класа из AppKit оквира, доступна само на macOS-у. Она представља афино преображај у дводимензионалном простору путем матрице 3×3. За разлику од CGAffineTransform-а из Core Graphics-а (који је доступан на iOS-у), NSAffineTransform је објектно-оријентисано омотање структуре CGAffineTransform, који додаје практичне методе за рад са NSBezierPath, NSPoint и NSSize.

Афино преображај — је такво преображај равни које чува релацију „тачка лежи на правој“ и паралелност правих. Другим ријечима, након афиног преображаја, паралелне линије остају паралелне, а праве — праве. Међутим, удаљености, углови и површине се могу мијењати: скалирање, ротација и кошење су посебни случајеви афиних преображаја.

На iOS-у, аналог NSAffineTransform-а је структура CGAffineTransform из Core Graphics-а. Оба API-ја се заснивају на истом математичком моделу — матрици афиног преображаја 3×3, гдје је последњи ред увијек [0, 0, 1]. Разлика је у томе што је NSAffineTransform класа (са retain/release у Objective-C-у), а CGAffineTransform је структура (вриједносни тип) у Swift-у и C-језику.

Врсте афиних трансформација

NSAffineTransform подржава четири основна типа трансформација: translate (помијерање), scale (скалирање), rotate (ротација) и shear (кошење). Сваки тип је представљен посебном методом и може бити примијењен како на постојећи објекат трансформације, тако и коришћен за стварање новог.

ОперацијаNSAffineTransform методаПараметриВизуелни ефекат
TranslatetranslateXBy:yBy:deltaX, deltaYПомијерање објекта дуж оса X и Y
ScalescaleBy: / scaleXBy:yBy:factor / scaleX, scaleYПовећање или смањивање величина
RotaterotateByDegrees: / rotateByRadians:угао у степенима или радијанимаРотација око почетка координата
ShearПутем setTransformStructкомпоненте m12, m21 матрицеКошење објекта дуж осе

Translate — помијерање

Translate додаје помијерање координатама свих тачака објекта. Параметри deltaX и deltaY одређују величину помијерања хоризонтално и вертикално. Позитивна вриједност deltaX помиче удесно, deltaY — нагоре. Translate не мијења облик или величину објекта — само његов положај.

Scale — скалирање

Scale множи координате тачака задатим фактором. Код равномјерног скалирања (један параметар) објекат се пропорционално повећава или смањује. Код неравномјерног скалирања облик се изобличује. Фактор 1.0 оставља величину непромијењеном, већи од 1.0 повећава, од 0.0 до 1.0 смањује. Негативне вриједности стварају огледало.

Rotate — ротација

Rotate ротира објекат око почетка координата за задати угао. Позитиван угао ротације одговара ротацији супротно од казаљке на сату. rotateByDegrees прихвата степене (0–360), rotateByRadians — радијане (0–2π). Ротација се увијек извршава у односу на тачку (0, 0), па је за ротацију око произвољне тачке потребно комбиновати rotate са translate.

Матрично представљање 3×3

Афино преображај у NSAffineTransform-у је представљен матрицом 3×3, гдје је последњи ред увијек [0, 0, 1]. Ово је стандардни математички приказ, који омогућава представљање комбинације трансформација као производа матрица. Структура матрице се одређује путем NSAffineTransformStruct, која садржи шест значајних компонената: m11, m12, m21, m22, tX, tY.

Компоненте m11, m12, m21, m22 су одговорне за скалирање, ротацију и кошење. Компоненте tX и tY су одговорне за помијерање. У стандардној конфигурацији (јединична матрица) m11 = 1, m22 = 1, остале су 0. За добијање тренутних вриједности матрице користи се transformStruct — својство NSAffineTransform-а које враћа структуру NSAffineTransformStruct.

Множење матрица је некомутативна операција. То значи да редослед примјене трансформација има значај: translate + rotate даје другачији резултат од rotate + translate. Приликом комбиновања, NSAffineTransform множи нову матрицу са лијеве стране на тренутну: newMatrix = operation × currentMatrix. Зато се последње додато преображај прво примјењује.

Комбиновање трансформација

NSAffineTransform омогућава комбиновање више трансформација у једном објекту. Сваки позив translateXBy:yBy:, scaleBy: или rotateByDegrees: мијења унутрашњу матрицу — множи тренутну матрицу матрицом одговарајућег преображаја. Ово омогућава стварање сложеног преображаја из секвенце једноставних операција.

За инвертовање комбинованог преображаја користи се метода invert. Инверзија ствара ново афино преображај које поништава оригинално: ако на тачку примијенимо оригинално преображај, па затим инвертовано, тачка се враћа у почетни положај. Инверзија је корисна за поништавање трансформације контекста прије цртања UI елемената који не треба да буду трансформисани.

Провјера да ли је преображај идентитетски (не мијења координате) може се извршити путем својства isIdentity. Идентитетско преображај је јединична матрица, при множењу са којом се координате тачке не мијењају. Нови објекат NSAffineTransform се креира као идентитетско преображај. Ово својство је корисно за оптимизацију: ако је преображај идентитетски, његова примјена се може прескочити.

Примјена на објекте и контекст

NSAffineTransform се може примијенити на четири типа објеката: NSPoint, NSSize, NSBezierPath и графички контекст NSGraphicsContext. За сваку намјену постоји посебна метода: transformPoint:, transformSize:, transformBezierPath: и set.

Трансформација тачака и величина

Метода transformPoint: множи матрицу преображаја вектором координата тачке (x, y, 1), враћајући нови положај тачке. transformSize: ради слично, али не узима у обзир компоненте tX и tY — помијерање се не примјењује, само скалирање, ротација и кошење. Ово је корисно за трансформацију вектора и величина које не треба да се помјерају.

Трансформација NSBezierPath путања

Метода transformBezierPath: ствара нови NSBezierPath објекат, чија је свака тачка трансформисана у складу са NSAffineTransform матрицом. Оригинални пут се не мијења — ствара се копија са трансформисаним координатама. Ово је скупа операција за сложене путање са великим бројем чворова.

Примјена на графички контекст

Метода set примјењује преображај на тренутни графички контекст (NSGraphicsContext), мијењајући његов CTM (Current Transformation Matrix). Након позива set, сва накнадна цртања у овом контексту биће трансформисана. За привремену трансформацију, користите saveGraphicsState / restoreGraphicsState прије и послије set.

Примјери кода у Swift-у

Размотримо практичне примјере коришћења NSAffineTransform-а у macOS апликацији за трансформацију графичких објеката.

Креирање и комбиновање преображаја

Примјер ствара NSAffineTransform који комбинује помијерање, ротацију и скалирање. Прво се објекат помиче за (100, 50), затим ротира за 45 степени и на крају повећава за 1.5 пута. Редослед је важан: rotate након translate даје ротацију у односу на нови почетак координата.

swift
import AppKit

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

// Примјена на тачку
let point = NSPoint(x: 10, y: 20)
let transformedPoint = transform.transform(point)

// Примјена на величину
let size = NSSize(width: 100, height: 50)
let transformedSize = transform.transform(size)

Трансформација контекста за цртање

Примјер показује примјену NSAffineTransform-а на графички контекст путем set и concat. Након примјене трансформације, сва накнадна цртања се одвијају у трансформисаном координатном систему. Чување стања графике путем saveGraphicsState омогућава повратак на оригиналну матрицу.

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

    // Цртање у трансформисаном координатном систему
    let path = NSBezierPath(roundedRect: NSRect(
        x: -50, y: -50,
        width: 100, height: 100
    ), xRadius: 10, yRadius: 10)
    NSColor.blue.setFill()
    path.fill()

    ctx.restoreGraphicsState()
}

Трансформација NSBezierPath путање

Примјер демонстрира креирање копије NSBezierPath-а са трансформисаним координатама. Оригинални пут остаје непромијењен, а трансформисана копија може се цртати одвојено — ово је корисно за стварање елемената који се понављају на различитим положајима.

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
}

Често постављана питања

По чему се NSAffineTransform разликује од CGAffineTransform?

NSAffineTransform — је класа из AppKit-а (само macOS), а CGAffineTransform — је структура из Core Graphics-а (iOS и macOS). NSAffineTransform је објектно-оријентисано омотање и пружа методе за рад са NSBezierPath-ом. CGAffineTransform је лагана структура вриједносног типа која се користи са CGPath-ом.

Како ротирати објекат око његовог центра?

За ротацију око центра, извршите три корака: 1) translate на центар објекта (помијерање почетка координата у центар), 2) rotate за жељени угао, 3) translate назад за негативни вектор центра. Комбинација translate—rotate—translate даје ротацију око произвољне тачке, а не око почетка координата.

Може ли се NSAffineTransform користити на iOS-у?

Не, NSAffineTransform је доступан само на macOS-у у оквиру AppKit-а. На iOS-у се користи структура CGAffineTransform из Core Graphics-а, која пружа аналогне могућности: CGAffineTransformMakeTranslation, CGAffineTransformMakeScale, CGAffineTransformMakeRotation и CGAffineTransformConcat.

Како поништити преображај?

Користите методу invert, која враћа инверзно преображај. Ако помножимо оригинално преображај са инверзним, добијамо јединичну матрицу (идентитетско преображај). За привремену примјену, позовите saveGraphicsState прије set и restoreGraphicsState послије.

Како направити огледало?

Користите негативну скалу: transform.scaleXBy(-1, yBy: 1) ствара хоризонтално огледало, а scaleXBy(1, yBy: -1) — вертикално. За огледало у односу на произвољну осу, комбинујте translate (помијерање на осу), scale са -1 и обрнути translate.

Резиме

  • NSAffineTransform — AppKit класа за афине трансформације са матрицом 3×3 на macOS-у
  • Четири основна типа: translate (помијерање), scale (скалирање), rotate (ротација) и shear (кошење)
  • Матрица 3×3 садржи шест значајних компонената: m11, m12, m21, m22, tX, tY
  • Редослед комбиновања трансформација утиче на резултат — множење матрица је некомутативно
  • Примјењује се на NSPoint, NSSize, NSBezierPath и графички контекст кроз CTM
  • Инверзија путем методе invert поништава дјеловање било ког афиног преображаја
  • На iOS-у, аналог је структура CGAffineTransform из Core Graphics-а

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође