libs-gui/Source/PSMatrix.m

199 lines
4 KiB
Mathematica
Raw Normal View History

/*
PSMatrix.m
Copyright (C) 1996 Free Software Foundation, Inc.
Author: Ovidiu Predescu <ovidiu@net-community.com>
Date: August 1997
This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <math.h>
#include <AppKit/config.h>
#include <AppKit/PSMatrix.h>
/* A Postscript matrix look like this:
/ a b 0 \
| c d 0 |
\ tx ty 1 /
*/
static const float pi = 3.1415926535897932384626433;
@implementation PSMatrix
+ matrixFrom:(float[6])_matrix
{
PSMatrix* m = [[self alloc] autorelease];
memcpy (m->matrix, _matrix, sizeof (m->matrix));
return m;
}
- init
{
[self makeIdentityMatrix];
rotationAngle = 0;
return self;
}
- (id)copyWithZone:(NSZone*)zone
{
PSMatrix* new = [isa alloc];
memcpy (new->matrix, matrix, sizeof(matrix));
new->rotationAngle = rotationAngle;
return new;
}
- (void)scaleBy:(float)sx :(float)sy
{
A *= sx; B *= sx;
C *= sy; D *= sy;
}
- (void)translateToPoint:(NSPoint)point
{
float newTX, newTY;
newTX = point.x * A + point.y * C + TX;
newTY = point.x * B + point.y * D + TY;
TX = newTX;
TY = newTY;
}
- (void)rotateByAngle:(float)angle
{
float newA, newB, newC, newD;
float angleRad = pi * angle / 180;
float sine = sin (angleRad);
float cosine = cos (angleRad);
newA = A * cosine + C * sine; newB = B * cosine + D * sine;
newC = -A * sine + C * cosine; newD = -B * sine + D * cosine;
A = newA; B = newB;
C = newC; D = newD;
rotationAngle += angle;
}
- (void)makeIdentityMatrix
{
A = 1; B = 0;
C = 0; D = 1;
TX = 0; TY = 0;
rotationAngle = 0;
}
- (void)setFrameOrigin:(NSPoint)point
{
float dx = point.x - TX;
float dy = point.y - TY;
[self translateToPoint:NSMakePoint (dx, dy)];
}
- (void)setFrameRotation:(float)angle
{
float newAngle = angle - rotationAngle;
[self rotateByAngle:newAngle];
}
- (float)rotationAngle
{
return rotationAngle;
}
- (void)concatenateWith:(PSMatrix*)other
{
float newA, newB, newC, newD, newTX, newTY;
newA = other->A * A + other->B * C;
newB = other->A * B + other->B * D;
newC = other->C * A + other->D * C;
newD = other->C * B + other->D * D;
newTX = other->TX * A + other->TY * C + TX;
newTY = other->TX * B + other->TY * D + TY;
A = newA; B = newB;
C = newC; D = newD;
TX = newTX; TY = newTY;
rotationAngle += other->rotationAngle;
}
- (void)inverse
{
float newA, newB, newC, newD, newTX, newTY;
float det;
det = A * D - B * C;
if (!det) {
NSLog (@"error: determinant of matrix is 0!");
return;
}
newA = D / det;
newB = -B / det;
newC = -C / det;
newD = A / det;
newTX = (-D * TX + C * TY) / det;
newTY = (B * TX - A * TY) / det;
NSDebugLog (@"inverse of matrix ((%f, %f) (%f, %f) (%f, %f))\n"
@"is ((%f, %f) (%f, %f) (%f, %f))",
A, B, C, D, TX, TY,
newA, newB, newC, newD, newTX, newTY);
A = newA; B = newB;
C = newC; D = newD;
TX = newTX; TY = newTY;
}
- (NSPoint)pointInMatrixSpace:(NSPoint)point
{
NSPoint new;
new.x = A * point.x + C * point.y + TX;
new.y = B * point.x + D * point.y + TY;
return new;
}
- (NSSize)sizeInMatrixSpace:(NSSize)size
{
NSSize new;
new.width = A * size.width + C * size.height + TX;
new.height = B * size.width + D * size.height + TY;
return new;
}
- (NSString*)description
{
return [NSString stringWithFormat:@"PSMatrix ((%f, %f) (%f, %f) (%f, %f))",
A, B, C, D, TX, TY];
}
@end /* PSMatrix */