home *** CD-ROM | disk | FTP | other *** search
- // MorphLine.m
- //
- // created by Martin Wennerberg on Sun 12-Nov-1995
- //
- // when who modification
-
- #import "MorphLine.h"
- #import "algebra.h"
-
- @implementation MorphLine
-
- - init
- {
- self = [super init];
- nPoints = 2;
- startPoints = NSZoneCalloc([self zone], nPoints, sizeof(NSPoint));
- endPoints = NSZoneCalloc([self zone], nPoints, sizeof(NSPoint));
- moveStartDelta = 0.0;
- moveEndDelta = 1.0;
- dissolveStartDelta = 0.0;
- dissolveEndDelta = 1.0;
-
- return self;
- }
-
- - initWithValuesInDict:(NSDictionary *)dict
- {
- NSArray *startPointsValues;
- NSArray *endPointsValues;
- NSNumber *number;
-
- self = [self init];
- if ([dict isKindOfClass:[NSString class]])
- dict = [(NSString *)dict propertyList];
-
- startPointsValues = [dict objectForKey:MLKEY_STARTPOINTS];
- endPointsValues = [dict objectForKey:MLKEY_ENDPOINTS];
- if (MIN([startPointsValues count], [endPointsValues count]) >= 2)
- {
- unsigned i;
-
- nPoints = MIN([startPointsValues count], [endPointsValues count]);
- free (startPoints);
- free (endPoints);
- startPoints = NSZoneCalloc([self zone], nPoints, sizeof(NSPoint));
- endPoints = NSZoneCalloc([self zone], nPoints, sizeof(NSPoint));
- for (i = 0; i < nPoints; ++i)
- {
- startPoints[i] = NSPointFromString([startPointsValues objectAtIndex:i]);
- endPoints[i] = NSPointFromString([endPointsValues objectAtIndex:i]);
- }
- }
- number = [dict objectForKey:MLKEY_MOVESTART];
- if (number != nil)
- [self setMoveStartDelta:[number floatValue]];
-
- number = [dict objectForKey:MLKEY_MOVEEND];
- if (number != nil)
- [self setMoveEndDelta:[number floatValue]];
-
- number = [dict objectForKey:MLKEY_DISSOLVESTART];
- if (number != nil)
- [self setDissolveStartDelta:[number floatValue]];
-
- number = [dict objectForKey:MLKEY_DISSOLVEEND];
- if (number != nil)
- [self setDissolveEndDelta:[number floatValue]];
-
- return self;
- }
-
- - (NSDictionary *)pList
- {
- NSMutableDictionary *dict;
- NSMutableArray *startPointStrings;
- NSMutableArray *endPointStrings;
- unsigned i;
-
- dict = [NSMutableDictionary dictionaryWithCapacity:10];
- startPointStrings = [NSMutableArray arrayWithCapacity:nPoints];
- endPointStrings = [NSMutableArray arrayWithCapacity:nPoints];
-
- for (i = 0; i < nPoints; ++i)
- {
- [startPointStrings addObject:NSStringFromPoint(startPoints[i])];
- [endPointStrings addObject:NSStringFromPoint(endPoints[i])];
- }
-
- [dict setObject:startPointStrings forKey:MLKEY_STARTPOINTS];
- [dict setObject:endPointStrings forKey:MLKEY_ENDPOINTS];
- [dict setObject:[[NSNumber numberWithFloat:[self moveStartDelta]] description] forKey:MLKEY_MOVESTART];
- [dict setObject:[[NSNumber numberWithFloat:[self moveEndDelta]] description] forKey:MLKEY_MOVEEND];
- [dict setObject:[[NSNumber numberWithFloat:[self dissolveStartDelta]] description] forKey:MLKEY_DISSOLVESTART];
- [dict setObject:[[NSNumber numberWithFloat:[self dissolveEndDelta]] description] forKey:MLKEY_DISSOLVEEND];
-
- return dict;
- }
-
- - (id) copyWithZone:(NSZone *)zone
- {
- MorphLine *newObject;
- NSDictionary *dict;
-
- dict = [self pList];
- newObject = [[[self class] allocWithZone:zone] initWithValuesInDict:dict];
- return newObject;
- }
-
- - (void) dealloc
- {
- free (startPoints);
- free (endPoints);
- [super dealloc];
- }
-
- - (NSPoint) startPointAtDelta:(float)d
- {
- if (d <= moveStartDelta || (moveEndDelta - moveStartDelta < 0.00001))
- return startPoints[0];
- if (d >= moveEndDelta)
- return startPoints[1];
- return pt_wmean (startPoints[0], startPoints[1], (d - moveStartDelta) / (moveEndDelta - moveStartDelta));
- }
-
- - (NSPoint) endPointAtDelta:(float)d
- {
- if (d <= moveStartDelta || (moveEndDelta - moveStartDelta < 0.00001))
- return endPoints[0];
- if (d >= moveEndDelta)
- return endPoints[1];
- return pt_wmean (endPoints[0], endPoints[1], (d - moveStartDelta) / (moveEndDelta - moveStartDelta));
- }
-
- // The following two methods for controlling the coordinates currently
- // only works when you have only two deltas (0 and 1). This can
- // be modified to handle any number of points.
- - (void) setStartPoint:(NSPoint)aPoint atDelta:(float)delta
- {
- if (delta < 0.5)
- startPoints[0] = aPoint;
- else
- startPoints[1] = aPoint;
- }
-
- - (void) setEndPoint:(NSPoint)aPoint atDelta:(float)delta
- {
- if (delta < 0.5)
- endPoints[0] = aPoint;
- else
- endPoints[1] = aPoint;
- }
-
-
- /****************************************************************
- * Morph Controlls
- ****************************************************************/
-
- - (void) setMoveStartDelta:(float)a
- {
- moveStartDelta = a;
- moveEndDelta = MAX (moveStartDelta, moveEndDelta);
- }
-
- - (void) setMoveEndDelta:(float)a
- {
- moveEndDelta = a;
- moveStartDelta = MIN (moveStartDelta, moveEndDelta);
- }
-
- - (void) setDissolveStartDelta:(float)a
- {
- dissolveStartDelta = a;
- dissolveEndDelta = MAX (dissolveStartDelta, dissolveEndDelta);
- }
-
- - (void) setDissolveEndDelta:(float)a
- {
- dissolveEndDelta = a;
- dissolveStartDelta = MIN (dissolveStartDelta, dissolveEndDelta);
- }
-
- - (float) moveStartDelta
- {
- return moveStartDelta;
- }
-
- - (float) moveEndDelta
- {
- return moveEndDelta;
- }
-
- - (float) dissolveStartDelta
- {
- return dissolveStartDelta;
- }
-
- - (float) dissolveEndDelta
- {
- return dissolveEndDelta;
- }
-
- /****************************************************************
- * maths
- ****************************************************************/
- - (NSAffineTransform *) transformFromDelta:(float) beforeDelta
- toDelta:(float) afterDelta
- // This method contains bugs that makes unusable. It would be nice to have, so I might fix it some day.
- // A messy, but working implementation of the transformation mathemathics can be found in Morphed.m
- {
- NSPoint s0, s1, e0, e1; // Start and end point coordinates of the lines 0 and 1
- NSAffineTransform *t;
- double scale;
-
- t = [NSAffineTransform transform];
-
- s0 = [self startPointAtDelta:beforeDelta];
- e0 = [self endPointAtDelta:beforeDelta];
- s1 = [self startPointAtDelta:afterDelta];
- e1 = [self endPointAtDelta:afterDelta];
-
- scale = pt_dist(e1, s1) / pt_dist(e0, s0);
-
- [t translateXBy:-s0.x yBy:-s0.y];
- [t rotateByRadians:- line_angle(s0, e0)];
- [t scaleXBy:scale yBy:1.0];
- [t rotateByRadians:line_angle(s1, e1)];
- [t translateXBy:s1.x yBy:s1.y];
-
- return t;
- }
-
- /****************************************************************
- * description
- ****************************************************************/
- - (NSString *) description
- {
- return [[self pList] description];
- }
-
- /****************************************************************
- * display
- ****************************************************************/
- - (void) drawInView:(NSView *)view delta:(float)delta
- {
- NSPoint startPt, endPt;
-
- startPt = [self startPointAtDelta:delta];
- endPt = [self endPointAtDelta:delta];
- PSmoveto (startPt.x, startPt.y);
- PSlineto (endPt.x, endPt.y);
- PSstroke();
- }
-
- - (BOOL) hitTest:(NSPoint) aPoint
- {
- return NO;
- }
- - (int) hitKnobTest: (NSPoint) aPoint
- {
- return NO;
- }
-
- @end
-