This is rotateprocs.c in view mode; [Download] [Up]
/* * (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved. * * (b) If this Sample Code is distributed as part of the Display PostScript * System Software Development Kit from Adobe Systems Incorporated, * then this copy is designated as Development Software and its use is * subject to the terms of the License Agreement attached to such Kit. * * (c) If this Sample Code is distributed independently, then the following * terms apply: * * (d) This file may be freely copied and redistributed as long as: * 1) Parts (a), (d), (e) and (f) continue to be included in the file, * 2) If the file has been modified in any way, a notice of such * modification is conspicuously indicated. * * (e) PostScript, Display PostScript, and Adobe are registered trademarks of * Adobe Systems Incorporated. * * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO * CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED * AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED. * ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY * OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO * WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY) * WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY * DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT * OF THIRD PARTY RIGHTS. */ /* * rotateprocs.c * * This file contains procedure that perform operations * on rotated rectangles and points. * * Note: the angle in the procedures below should be expressed * in radians and not degrees. */ #import <appkit/graphics.h> #import <appkit/nextstd.h> #import <math.h> /* * Takes the point passed in, rotates it around the point * at the angle given and returns the new point. * The new point replaces the old one and its address * is returned as the return value. */ NXPoint *RotatePoint(NXPoint *aPoint, NXPoint *cPoint, float angle) { float d, dx, dy; float ang; if (aPoint && cPoint && angle != 0) { dx = aPoint->x - cPoint->x; dy = aPoint->y - cPoint->y; *aPoint = *cPoint; d = sqrt(dx * dx + dy * dy); if (d != 0.0) { ang = angle + (float) atan2(dy, dx); aPoint->x += d * cos(ang); aPoint->y += d * sin(ang); } } return aPoint; } /* * Checks whether the point passed in lies in the rectangle * rotated about its lower left vertice at the angle provided. * Returns either YES or NO. Assumes an unflipped * coordinate system. */ BOOL MouseInRotatedRect(NXPoint *aPoint, NXRect *aRect, float angle) { NXPoint pt; if (aRect && aPoint) { pt = *aPoint; RotatePoint(&pt, &aRect->origin, -angle); return NXMouseInRect(&pt, aRect, NO); } else return NO; } /* * This procedure takes the unrotated rectangle, bRect, * rotates it around the point, cPoint, at the angle, angle, * and places the new bounding box that encloses the * rotated rectangle in the rectangle aRect. The address * of the new rectangle is returned as the return value. * * Figuring the new width and height is relatively * straight-forward. Just take the sin and cos of the * old width and height. * * Figuring the new origin is a bit different. The vertices * for the lower x and lower y coordinates are chosen * based on the angle to rotate. Their positions in the rotated * spaced are calculated and subtracted from the center point. */ NXRect *RotateRectBounds(NXRect *aRect, const NXRect *bRect, NXPoint *cPoint, float angle) { float dx, dy, dxx, dxy, dyx, dyy; double cosa, sina; if (aRect && bRect && cPoint) { if (angle != 0) { cosa = cos(angle); sina = sin(angle); dyx = dxx = bRect->origin.x - cPoint->x; dyy = dxy = bRect->origin.y - cPoint->y; if (cosa > 0) { if (sina > 0) dxy += bRect->size.height; else dyx += bRect->size.width; } else { if (sina > 0) { dxx += bRect->size.width; dyy = dxy = dxy + bRect->size.height; } else { dyx = dxx = dxx + bRect->size.width; dyy += bRect->size.height; } } aRect->origin = *cPoint; dx = sqrt(dxx * dxx + dxy * dxy); if (dx != 0.0) aRect->origin.x += (float) dx * cos(angle + atan2(dxy, dxx)); dy = sqrt(dyx * dyx + dyy * dyy); if (dy != 0.0) aRect->origin.y += (float) dy * sin(angle + atan2(dyy, dyx)); aRect->size.width = (float) (ABS(bRect->size.width * cosa) + ABS(bRect->size.height * sina)); aRect->size.height = (float) (ABS(bRect->size.width * cos(M_PI_2 - angle)) + ABS(bRect->size.height * sin(M_PI_2 - angle))); } else *aRect = *bRect; } return aRect; } /* * This procedure takes two rectangles and an angle. * It checks if the second rectangle rotated about its origin * at the given angle intersects the first rectangle. The * first rectangle is unrotated. * * It checks for intersection by getting the frame for the rotated * rectangle and then checking the intersection. */ BOOL IntersectsRotatedRect(NXRect *aRect, NXRect *bRect, float angle) { NXRect rect; if (aRect && bRect) { if (angle != 0.0) { RotateRectBounds(&rect, bRect, &bRect->origin, angle); bRect = ▭ } return NXIntersectsRect(aRect, bRect); } return NO; } /* * This procedure takes two points and constrains the first * point to the nearest 15% interval. */ void ConstrainPointToAngle(NXPoint *aPoint, NXPoint *cPoint, float angle) { float d, dx, dy, a; dx = aPoint->x - cPoint->x; dy = aPoint->y - cPoint->y; d = sqrt(dx*dx + dy*dy); if (d != 0.0) { a = rint(atan2(dy, dx) / angle) * angle; aPoint->x = (float) cPoint->x + d * cos(a); aPoint->y = (float) cPoint->y + d * sin(a); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.