Fixes to appending an arc

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@9252 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Nicola Pero 2001-03-01 01:47:32 +00:00
parent 94fe65783b
commit c76c32bc0f

View file

@ -828,103 +828,132 @@ static Class NSBezierPath_concrete_class = nil;
[self lineToPoint: points[i]]; [self lineToPoint: points[i]];
} }
- (void)appendBezierPathWithOvalInRect:(NSRect)aRect - (void) appendBezierPathWithOvalInRect: (NSRect)aRect
{ {
[self appendBezierPath: [isa bezierPathWithOvalInRect: aRect]]; [self appendBezierPath: [isa bezierPathWithOvalInRect: aRect]];
} }
- (void)appendBezierPathWithArcWithCenter:(NSPoint)center /* startAngle and endAngle are in degrees, counterclockwise, from the
radius:(float)radius x axis */
startAngle:(float)startAngle - (void) appendBezierPathWithArcWithCenter: (NSPoint)center
endAngle:(float)endAngle radius: (float)radius
clockwise:(BOOL)clockwise startAngle: (float)startAngle
endAngle: (float)endAngle
clockwise: (BOOL)clockwise
{ {
NSBezierPath *path = [isa bezierPath]; float startAngle_rad, endAngle_rad, diff;
float strtangrd, endangrd, diff;
NSPoint p0, p1, p2, p3; NSPoint p0, p1, p2, p3;
while(startAngle < 0) while (startAngle < 0)
startAngle = startAngle + 360; startAngle = startAngle + 360;
while(startAngle > 360) while (startAngle > 360)
startAngle = startAngle - 360; startAngle = startAngle - 360;
while(endAngle < 0) while (endAngle < 0)
endAngle = endAngle + 360; endAngle = endAngle + 360;
while(endAngle > 360) while (endAngle > 360)
endAngle = endAngle - 360; endAngle = endAngle - 360;
strtangrd = PI * startAngle / 180; /* Convert the angles to radians */
endangrd = PI * endAngle / 180; startAngle_rad = PI * startAngle / 180;
endAngle_rad = PI * endAngle / 180;
p0 = NSMakePoint(center.x + radius * cos(strtangrd), center.y + radius * sin(strtangrd)); /* Start point */
[path moveToPoint: p0]; p0 = NSMakePoint (center.x + radius * cos (startAngle_rad),
center.y + radius * sin (startAngle_rad));
[self moveToPoint: p0];
if (clockwise) if (clockwise)
{ {
diff = -PI / 2; diff = -PI / 2;
if (strtangrd < endangrd) if (startAngle_rad < endAngle_rad)
strtangrd += 2 * PI; {
startAngle_rad += 2 * PI;
}
} }
else else
{ {
diff = PI / 2; diff = PI / 2;
if (strtangrd > endangrd) if (startAngle_rad > endAngle_rad)
strtangrd -= 2 * PI; {
startAngle_rad -= 2 * PI;
}
} }
while (strtangrd > endangrd) while ((clockwise) ? (startAngle_rad > endAngle_rad)
{ : (startAngle_rad < endAngle_rad))
if (strtangrd + diff >= endangrd) {
{ /* Add a quarter circle */
float sin_sta = sin(strtangrd); if ((clockwise) ? (startAngle_rad + diff >= endAngle_rad)
float cos_sta = cos(strtangrd); : (startAngle_rad + diff <= endAngle_rad))
{
// FIXME: Add a quarter circle, for clockwise the signs are not correct! float sin_start = sin (startAngle_rad);
p1 = NSMakePoint(center.x + radius * (cos_sta - KAPPA * sin_sta), float cos_start = cos (startAngle_rad);
center.y + radius * (sin_sta + KAPPA * cos_sta)); float sign = (clockwise) ? -1.0 : 1.0;
p2 = NSMakePoint(center.x + radius * (KAPPA * cos_sta -sin_sta),
center.y + radius * (cos_sta + KAPPA * sin_sta)); p1 = NSMakePoint (center.x
p3 = NSMakePoint(center.x + radius * (-sin_sta), + radius * (cos_start - KAPPA * sin_start * sign),
center.y + radius * cos_sta); center.y
[path curveToPoint: p3 controlPoint1: p1 controlPoint2: p2]; + radius * (sin_start + KAPPA * cos_start * sign));
strtangrd += diff; p2 = NSMakePoint (center.x
} + radius * (-sin_start * sign + KAPPA * cos_start),
else center.y
{ + radius * (cos_start * sign + KAPPA * sin_start));
float diff_ang = (endangrd - strtangrd) / 2; p3 = NSMakePoint (center.x + radius * (-sin_start * sign),
float cos_da = cos(diff_ang); center.y + radius * cos_start * sign);
float sin_da = sin(diff_ang);
double x, y; [self curveToPoint: p3 controlPoint1: p1 controlPoint2: p2];
float sin_sta = sin(strtangrd + diff_ang); startAngle_rad += diff;
float cos_sta = cos(strtangrd + diff_ang); }
else
x = (4 - cos_da) / 3; {
y = ((1- cos_da) * (cos_da - 3)) / (3 * sin_da); /* Add the missing bit
// FIXME: Add just the missing bit, for clockwise the signs are not correct! * We require that the arc be less than a semicircle.
p1 = NSMakePoint(center.x + radius * (cos_sta * x - sin_sta * y), * The arc may go either clockwise or counterclockwise.
center.y + radius * (sin_sta * y + cos_sta * x)); * The approximation is a very simple one: a single curve
p2 = NSMakePoint(center.x + radius * (cos_sta * x + sin_sta * y), * whose middle two control points are a fraction F of the way
center.y + radius * (sin_sta * (-y) + cos_sta * x)); * to the intersection of the tangents, where
p3 = NSMakePoint(center.x + radius * cos(endangrd), * F = (4/3) / (1 + sqrt (1 + (d / r)^2))
center.y + radius * sin(endangrd)); * where r is the radius and d is the distance from either tangent
[path curveToPoint: p3 controlPoint1: p1 controlPoint2: p2]; * point to the intersection of the tangents. This produces
break; * a curve whose center point, as well as its ends, lies on
} * the desired arc.
*/
NSPoint ps = [self currentPoint];
/* tangent is the tangent of half the angle */
float tangent = tan ((endAngle_rad - startAngle_rad) / 2);
/* trad is the distance from either tangent point to the
intersection of the tangents */
float trad = radius * tangent;
/* pt is the intersection of the tangents */
NSPoint pt = NSMakePoint (ps.x - trad * sin (startAngle_rad),
ps.y + trad * cos (startAngle_rad));
/* This is F - in this expression we need to compute
(trad/radius)^2, which is simply tangent^2 */
float f = (4.0 / 3.0) / (1.0 + sqrt (1.0 + (tangent * tangent)));
p1 = NSMakePoint (ps.x + (pt.x - ps.x) * f, ps.y + (pt.y - ps.y) * f);
p3 = NSMakePoint(center.x + radius * cos (endAngle_rad),
center.y + radius * sin (endAngle_rad));
p2 = NSMakePoint (p3.x + (pt.x - p3.x) * f, p3.y + (pt.y - p3.y) * f);
[self curveToPoint: p3 controlPoint1: p1 controlPoint2: p2];
break;
}
} }
} }
- (void)appendBezierPathWithArcWithCenter:(NSPoint)center - (void) appendBezierPathWithArcWithCenter: (NSPoint)center
radius:(float)radius radius: (float)radius
startAngle:(float)startAngle startAngle: (float)startAngle
endAngle:(float)endAngle endAngle: (float)endAngle
{ {
[self appendBezierPathWithArcWithCenter: center radius: radius [self appendBezierPathWithArcWithCenter: center radius: radius
startAngle: startAngle endAngle: endAngle clockwise: NO]; startAngle: startAngle endAngle: endAngle clockwise: NO];
} }
- (void)appendBezierPathWithArcFromPoint:(NSPoint)point1 - (void) appendBezierPathWithArcFromPoint: (NSPoint)point1
toPoint:(NSPoint)point2 toPoint: (NSPoint)point2
radius:(float)radius radius: (float)radius
{ {
// TODO // TODO
} }
@ -1326,9 +1355,9 @@ typedef struct _PathElement
INVALIDATE_CACHE(); INVALIDATE_CACHE();
} }
- (void)curveToPoint:(NSPoint)aPoint - (void) curveToPoint: (NSPoint)aPoint
controlPoint1:(NSPoint)controlPoint1 controlPoint1: (NSPoint)controlPoint1
controlPoint2:(NSPoint)controlPoint2 controlPoint2: (NSPoint)controlPoint2
{ {
PathElement elem; PathElement elem;
@ -1666,3 +1695,4 @@ static void flatten(NSPoint coeff[], float flatness, NSBezierPath *path)
[path lineToPoint: coeff[3]]; [path lineToPoint: coeff[3]];
} }
} }