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. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης